目录
一、二叉搜索树
1.1、什么是二叉搜索树
二叉搜索树或者是一棵空树;或者是具有下列性质的二叉树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值
- 若它的右子树不空,则右子树上所有结点的值均大于它的根节点的值
- 它的左、右子树分别为二叉搜索树
1.2、二叉搜索树的插入
新插入的节点一定是一个新添加的叶子节点,并且是查找不成功是查找路径上访问的最后一个节点的左孩子或右孩子节点。
若从空树出发,经过一系列的插入操作之后,可生成一棵二叉搜索树。
1.3、二叉搜索树的删除
从一棵二叉搜索树中删除一个节点 z 的整个策略分为三种基本情况:
- 如果 z 没有孩子节点,那么只是简单地将它删除,并修改它的父节点,用空节点作为孩子来替换 z
- 如果 z 只有一个孩子,那么将这个孩子提升到树中 z 的位置上,并修改 z 的父节点,用 z 的孩子替换 z
- 如果 z 有两个孩子,则以其中序遍历时 z 的前驱或后继替换 z ,然后再将其前驱或后继删除,这样就转换为上述两种情况
1.4、二叉搜索树的查找分析
当二叉搜索树不空时,首先将给定值和根节点的关键字比较,若相等,则查找成功,否则将依据给定值和根节点的关键字之间的大小关系,分别在左子树或右子树上继续进行查找。
当插入的关键字有序时,构成的二叉搜索树变为单支树。树的深度为 n ,其平均查找长度为 (n + 1) / 2,这是最差的情况。最好的情况是二叉搜索树的形态和折半查找的判定树相同,其平均查找长度和 logn 成正比。在随机情况下,二叉搜索树的平均查找长度和 logn 是等数量级的。
1.5、平衡的二叉搜索树
当输入的数据不随机,或者经过插入或删除操作后,可能会导致二叉搜索树的左右子树深度相差太大,而这会造成搜索效率低下,因此需要保持二叉搜索树的平衡。
有多种特殊结构如 AVL-tree、RB-tree、AA-tree,均可实现平衡二叉搜索树。
二、AVL树
2.1、什么是AVL树
AVL树(Adelson-Velskii-Landis tree),它或者是一棵空树,或者是具有下列性质的二叉树:它的左子树和右子树都是AVL树,且左子树和右子树的深度之差的绝对值不超过1。
2.2、生成AVL树
我们希望由任何初始序列构成的二叉搜索树都是AVL树。因为AVL树上任何节点的左右子树的深度之差都不超过1,它的深度和 logn 是同数量级的。由此,它的平均查找长度也和 logn 同数量级。
为了保持二叉搜索树的平衡,在插入节点时需要进行相应的操作。一般情况下,假设由于在二叉搜索树上插入节点而失去平衡的最小子树根节点的指针为 a(即 a 是离插入节点最近,且平衡因子绝对值超过1的祖先节点),则失去平衡后进行调整的规律可分为下列4种情况:
- 单向右旋平衡处理:由于在 *a 的左子树根节点的左子树上插入节点,*a 的平衡因子由1增至2,致使以 *a 为根的子树失去平衡,则需进行一次向右的顺时针旋转操作
- 单向左旋平衡处理:由于在 *a 的右子树根节点的右子树上插入节点,*a 的平衡因子由-1变为-2,致使以 *a 为根的子树失去平衡,则需进行一次向左的逆时针旋转操作
- 双向旋转(先左后右)平衡处理:由于在 *a 的左子树根节点的右子树上插入节点,*a 的平衡因子由1变为2,致使以 *a 为根的子树失去平衡,则需进行两次旋转(先左旋后右旋)操作
- 双向旋转(先右后左)平衡处理:由于在 *a 的右子树根节点的左子树上插入节点,*a 的平衡因子由-1变为-2,致使以 *a 为根的子树失去平衡,则需进行两次旋转(先右旋后左旋)操作
经过平衡旋转处理之后,以 *b 或 *c 为根的新子树为AVL树,且它的深度和插入之前以 *a 为根的子树相同。因此,当平衡的二叉搜索树因插入节点而失去平衡时,仅需对最小不平衡子树进行平衡旋转处理即可。因为经过旋转处理之后的子树深度和插入之前相同,因而不影响插入路径上所有祖先节点的平衡度。
三、红黑树
3.1、红黑树及其性质
红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是RED或BLACK。通过对任何一条从根到叶子的简单路径上各个节点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而是近似于平衡的。
一棵红黑树是满足下面红黑性质的二叉搜索树:
- 每个节点或者是红色的,或者是黑色的
- 根节点是黑色的
- 每个叶节点是黑色的
- 如果一个节点是红色的,则它的两个子节点都是黑色的
- 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
一棵有 n 个内部节点的红黑树的高度至少是 2lg(n + 1)。
从根到叶节点(不包括根节点)的任何一条简单路径上都至少有一半的节点为黑色,因为,根据第4条性质可知,一条简单路径上不可能有两个相邻的红色节点。
3.2、红黑树的插入操作
根据第5条性质可知,新插入的节点必须为红色。根据第4条性质可知,新插入节点的父节点必须为黑色。当新节点根据二叉搜索树的规则到达其插入点,却未能符合上述条件时,必须调整节点颜色并旋转树形。
设 z 表示待插入的节点,z 的父节点为 z.p,z.p 的兄弟节点为 y
插入情况共有6种,其中三种与另外三种是对称的。这取决于 z 的父节点 z.p 是 z 的祖父节点 z.p.p 的左孩子,还是右孩子:
3.2.1、z.p 是 z.p.p 的左孩子
-
1、y 节点是红色的
-
2、y 节点是黑色的且 z 是一个右孩子
-
3、y 节点是黑色的且 z 是一个左孩子
情况2先进行一次左转,变为情况3,然后再进行一次右转。(旋转方式与AVL树的“先左后右”旋转方式相同,详情请参考2.2、生成AVL树)
3.2.2、z.p 是 z.p.p 的右孩子
- 1、y 节点是红色的
- 2、y 节点是黑色的且 z 是一个左孩子
- 3、y 节点是黑色的且 z 是一个右孩子
情况2先进行一次右转,变为情况3,然后再进行一次左转。(旋转方式与AVL树的“先右后左”旋转方式相同,详情请参考2.2、生成AVL树)