数据结构-树(中)-二叉搜索树
最后更新:2017-12-18
前言
此文内容来自于 中国大学Mooc(慕课)-浙江大学-数据结构-第四讲-树(中), 老师原本内容是 C语言,本文把内容改为Swift.
1.1 定义
二叉搜索树又称二叉排序树或二叉查找树; 当该树不为空的时候,满足如下性质:
- 非空 左子树 的 所有键值小于其根节点的 键值;
- 非空 右子树 的 所有键值大于其根节点的 键值;
- 左右子树都是二叉搜索树
如下图:
2.1 二叉搜索树操作函数
二叉搜索树的操作函数:
- 查找某个元素返回节点地址;
- 查找最小/最大元素返回节点地址;
- 插入某个元素(Insert);
- 删除某个元素(delete);
2.1.1 查找某个元素值
步骤:
- 查找从根节点开始, 如果树为空, 返回 nil
- 非空树, 则根节点值与X相比较
- 如果 X 与根节点值相等(==), 搜索完成,返回此节点的地址;
- 如果 X 比根节点值小(<), 只需在 左子树 中继续搜索;
- 如果 X 比根节点值大(>), 只需在 右子树 中继续搜索;
递归方式
为了使函数有更好的扩展性, 此处使用了泛型
// Swift 语言实现
class Node <Element> {
var value : Element
var left : Node?
var right : Node?
init(value : Element) {
self.value = value
}
}
func find <T : Comparable> (_ value : T, in tree: Node<T>?) -> Node<T>? {
guard let node = tree else { return nil }
if value == node.value {
return node
} else if value < node.value {
return find(value, in: node.left) // 尾递归
} else {
return find(value, in: node.right) // 尾递归
}
}
更多尾递归信息可参考: http://www.ruanyifeng.com/blog/2015/04/tail-call.html
迭代函数
func iterFind <T: Comparable>(_ value : T, in tree: Node<T>?) -> Node<T>? {
var tmpNode = tree
while let node = tmpNode {
if value == node.value {
return node
} else if value < node.value {
tmpNode = node.left
} else {
tmpNode = node.right
}
}
return nil
}
2.1.2 查找最大最小值
根据二叉树的特性,我们很容易得到:
- 最大元素 一定是在树的最右分枝的端节点上
- 最小元素 一定是在树的最左分枝的端节点上
// 最大值迭代方式实现
func findMaxNode<T : Comparable>(in tree: Node<T>?) -> Node<T>? {
guard var node = tree else { return nil }
while let right = node.right {
node = right
}
return node
}
// 最小值采用递归方式
func findMinNode<T : Comparable>(in tree: Node<T>?) -> Node<T>? {
guard let node = tree else { return nil }
if node.left == nil {
return node
} else {
return findMinNode(in: node)
}
}
练习: 实现最大值采用递归方式 以及 最小值采用迭代方式
2.1.3 插入(Insert)某个元素
与查找相似,需要找到对应的位置. 然后递归/循环来处理。
// 递归
func insert<T:Comparable>(_ node: Node<T> , in tree : Node<T>?) -> Node<T> {
guard let tree = tree else { return node }
if node.value < tree.value {
tree.left = insert(node, in: tree.left)
} else if node.value > tree.value {
tree.right = insert(node, in: tree.right)
} else {
fatalError("Node value can not be equal")
}
return tree
}
2.1.4 删除(delete)某个元素
删除元素需要考虑三种情况:
-
删除的是叶节点,即没有子节点的节点;
- 直接删除, 然后将其父节点的指针置空,
- 直接删除, 然后将其父节点的指针置空,
-
删除只有一个子节点的节点;
- 将其父节点指向其子节点
- 将其父节点指向其子节点
-
删除具有左右子树的节点。
- 取左边最大的节点 或者 右边最小的节点 的 值来替换,然后删除被替换的节点
- 取左边最大的节点 或者 右边最小的节点 的 值来替换,然后删除被替换的节点
// 删除某个节点
func delete<T:Comparable>(_ node: Node<T> , in tree : Node<T>?) -> Node<T>? {
guard var tree = tree else {
print("Tree 没有, 找不到对应的Node")
return nil
}
if node.value < tree.value {
tree.left = delete(node, in: tree.left)
} else if node.value > tree.value {
tree.right = delete(node, in: tree.right)
} else {
// 左右都不为空,取右边的最小值
if tree.left != nil && tree.right != nil {
guard let rightMinNode = findMinNode(in: tree.right) else {
return tree
}
// 将节点的值替换
tree.value = rightMinNode.value
// 删除右边最小的节点
tree.right = delete(rightMinNode, in: tree.right)
} else if tree.left != nil {
// 一个左节点, 直接置空就好了
tree.left = nil
} else if tree.right != nil {
// 一个右节点, 直接置空就好了
tree.right = nil
} else {
// 两个节点都为nil
return nil
}
}
return tree
}