完全二叉树的判断
采用层序遍历:
- 如果节点的度为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
}