前面学习了树的基本术语、性质,以及二叉树的形态、遍历方法等,这次会继续学习两种“新”二叉树
Binary Search Tree
定义
二叉搜索树(BST,Binary Search Tree),也成为二叉排序树或二叉查找树。
二叉搜索树:前提得是一棵二叉树,可以为空;如果不为空,满足以下性质:
- 非空左子树的所有键值小于其根结点的键值
- 非空右子树的所有键值大于其根节点的键值
- 左、右子树都是二叉搜索树
特别函数
二叉搜索树本质上还是二叉树,所以其抽象数据类型描述与二叉树是一致的,但操作集存在差异,多了几个特别函数:
- Position Find(ElementType X, BinTree BST),从二叉搜索树
BST
中查找元素X
,返回其所在结点的地址 - Position FindMin(BinTree BST),从二叉搜索树
BST
中查找并返回最小元素所在结点的地址 - Position FindMax(BinTree BST),从二叉搜索树
BST
中查找并返回最大元素所在结点的地址 - BinTree Insert(ElementType X, BinTree BST),向二叉搜索树中插入结点
- BinTree Delete(ElementType X, BinTree BST),在二叉搜索树中删除结点
下面以二叉树的链式存储结构为准,完成几个常用的特别函数。
查找
查找函数的实现思路比较直接,按照二叉搜索树的性质,比根结点小则在左子树中查找,比根节点大则在右子树中查找,循环这个过程即可。
递归
1 | Position Find(ElementType X, BinTree BST) { |
非递归
1 | Position IterFind(ElementType X, BinTree BST) { |
查找最值
有了前面查找的思路后,根据 BST 的性质,直接查找最值的函数也很容易得到。
递归
1 | Position FindMax(BinTree BST) { |
非递归
1 | Position FindMax(BinTree BST) { |
插入
插入的关键在于先确定好插入的位置,既然要确定位置,那么就可以借助查找的思路。
递归
1 | BinTree Insert( BinTree BST, ElementType X ) { |
非递归
1 | BinTree Insert( BinTree BST, ElementType X ) { |
删除
删除的思路与插入的思路也类似,还是需要先找删除的位置。但是针对删除结点的不同(叶结点和非叶结点),需要分别考虑。如果删除的是叶结点,那么可以直接删除;但若删除非叶结点,就需要在删除这个结点后,用另一结点替代被删除结点,这样才不会使链式结构断裂。
对于度为 1 的被删除结点,另一结点直接使用其子结点即可;对于度为 2 的被删除结点,另一结点可以用其右子树的最小元素或者其左子树的最大元素,之所要用这两个结点,因为这两个结点一定是叶结点,可以直接拿掉。
1 | BinTree Delete( BinTree BST, ElementType X ) { |
Balanced Tree
平衡二叉树需要引入平衡因子的概念,其解决了二叉搜索树中出现“单枝树”而导致查找效率过低的树形结构问题。
平衡因子(Balance Factor,BF):,其中和分别为树 T 的左右子树高度。
定义
平衡二叉树(Balanced Tree,也叫 AVL 树):空树,或者任何一结点左右子树高度差的绝对值不超过 1,即。
调整
平衡二叉树的结构调整情况有以下四种情况,关键在于观察离破坏者最近的被破坏者和破坏者之间的位置关系。
但是要注意有时候插入元素即便不需要调整结构,也可能需要重新计算一些平衡因子。
RR旋转(虽然叫 RR 旋转,但是实际过程是左旋),破坏者位于被破坏者的右子树的右子树下。
1 | Tree RRrotate(Tree root) { |
LL旋转(虽然叫 LL 旋转,但是实际过程是右旋),破坏者位于被破坏者的左子树的左子树下。
1 | Tree LLrotate(Tree root) { |
LR旋转(与名称一致,先左旋后右旋),破坏者位于被破坏者的左子树的右子树下。
1 | Tree LRrotate(Tree root) { |
RL旋转(与名称一致,先右旋后左旋),破坏者位于被破坏者的右子树的左子树下。
1 | Tree RLrotate(Tree root) { |
Homework
04-4 是否同一棵二叉搜索树
这道题与树的同构有点像,下面的代码包含两种做法:
- 构造两棵树,判断两棵树是否一致
- 只构造一棵树,判断给定序列顺序是否与树的结点序列一致
1 | /* method 1: use recursion to judge two trees is same or not */ |
04-5 Root of AVL Tree
这道题就是何老师讲的平衡二叉树的四种旋转方式,题目一次将四种旋转方式全部考察到了,出的很好。
1 |
|
04-6 Complete Binary Search Tree
这道题很有难度,要对完全二叉树、二叉查找树及二叉树的遍历有较深的理解才能解出来,不过解不出来也没事,姥姥后面会讲。
1 |
|
04-7 二叉搜索树的操作集
这道题目是用来测试二叉搜索树常用操作的,可以尝试多种不同的写法来提交来验证是否正确。
1 |
|