二叉树简单问题记录

106 阅读1分钟

完全二叉树的判断

采用层序遍历:

  • 如果节点的度为2,继续下一个节点
  • 如果节点的度为1或者0,标记为检测模式,以后的节点的度都必须为0
  • 如果在检测模式中,并且该节点的父节点度为1时,如果还有剩余没有处理的节点,那么就不是完全二叉树
func isCompleteBinaryTree() -> Bool {
	var todo: [Node] = [self]
    var levelLeftCount = 1
    var isDangerous = false
    while todo.count > 0 {
		let cur = todo.removeFirst()
        if let left = cur.leftNode() {
        	todo.append(left)
		}
        if let right = cur.rightNode() {
        	todo.append(right)
        }
        
        if isDangerous {
        	if cur.degree != 0 {
            	return false
            }
            if let parent = parentNode(), parent.degree == 1 {
            	return todo.count > 0
            }
        } else if cur.degree < 2 {
        	isDangerous = true
        }
            
        levelLeftCount = levelLeftCount - 1
        if levelLeftCount <= 0 {
        	levelLeftCount = todo.count
        }
    }
    return true
}

重构二叉树

这个做起来很繁琐,并没有什么特别难的,代码也写得很不漂亮,所以我就不留代码了。

通过前序遍历、中序遍历的结果,或者后序遍历、中序遍历的结果,得到的。以“前序遍历、中序遍历”举例:

前序遍历可以这样表示:头节点 |(n 个左子树上的节点)|(m 个左子树上的节点) 中序遍历可以这样表示:(n 个左子树上的节点)| 头节点 |(m 个左子树上的节点)

前驱节点

前驱节点是指中序遍历后当前节点前面的那个节点

  • 如果当前节点有左子树,那么就是左子树上最右的节点
  • 如果当前节点没有左子树,那么就是当前节点父节点中最近一个符合这个条件的节点:当前节点位于该祖先节点的右子树
func preNode() -> Node? {
    // 有左子树: 左子树的最右节点
    if let left = leftNode() {
        var rightest: Node? = left
        while rightest?.rightNode() != nil {
            rightest = rightest?.rightNode()
        }
        return rightest
    } else { // 没有左子树
        var result: Node? = self
        while let cur = result {
            if cur.isRightNode {
                return cur.parentNode()
            }
            result = cur.parentNode()
        }
    }
    return nil
}

删除节点

  • 如果节点是叶子节点,就直接删除节点
  • 如果节点是非叶子节点,就找到前驱节点或者后继节点替代这个节点
@discardableResult
    func removeNode(_ value: Int) -> Node? {
        guard let nodeToRemove = findNode(value: value) else {
            return nil
        }
        return remove(node: nodeToRemove, priorityPre: priorityPre(nodeToRemove: nodeToRemove))
    }
    
    func remove(node: Node, priorityPre: Bool) -> Node? {
        if node.isLeafNode {
            if let parent = node.parentNode() {
                if node.isLeftNode {
                    parent.left = nil
                } else if node.isRightNode {
                    parent.right = nil
                }
            } else {
                // 将 root 置空
            }
            return node
        } else {
            let replaced: Node?
            if priorityPre {
                replaced = node.preNode() ?? node.nextNode()
            } else {
                replaced = node.nextNode() ?? node.preNode()
            }
            guard let replace = replaced else {
                return nil
            }
            node.value = replace.value
            return remove(node: replace, priorityPre: priorityPre)
        }
    }
    
    func findNode(value: Int) -> Node? {
        var history: [Node] = []
        var cur: Node? = self
        while history.count != 0 || cur != nil {
            if let curNode = cur {
                if curNode.value == value {
                    return curNode
                }
                history.append(curNode)
                cur = cur?.leftNode()
            } else if let curNode = history.popLast() {
                cur = curNode.rightNode()
            }
        }
        return nil
    }