目录
二叉排序树
平衡二叉树
平衡二叉树的删除
红黑树
红黑树的插入
红黑树的删除
二叉排序树
- 二叉排序树的定义
- 👩💻 左子树结点值 < 根节点值 < 右子树结点值
- 默认不允许两个结点的关键字相同
- 查找操作
- 从根节点开始,目标值更小往左找,目标值更大往右找
- 插入操作
- 找到应该插入的位置(一定是叶子节点),一定要注意修改其父节点指针
- 👩💻 删除操作
- 被删结点为叶子节点,直接删除
- 被删结点只有左或只有右子树,用其字数顶替其位置
- 被删结点由左、右子树
- 可用其后继节点顶替,再删除后继节点
- 或用其前驱节点顶替,再删除前驱节点
- 前驱:左子树中最有下的结点
- 后继:右子树中最左下的结点
- 查找效率分析
- 取决于树的高度,最好O(logn),最坏O(n)
- 👩💻 平均查找长度的计算
- 查找成功的情况
- 查找失败的情况(需补充失败节点)
平衡二叉树
- 定义
- 树上任一结点的左子树和右子树的高度之差不超过1
- 结点的平衡因子 = 左子树高 - 右子树高
- 插入操作
- 和二叉排序树一样,找合适的位置插入
- 新插入的结点可能导致其祖先们平衡因子改变导致失衡
- 👩💻 调整“不平衡”
- 找到最小不平衡子树进行调整,记最小不平衡子树的根为A
- LL:在A的左孩子的左子树插入导致A不平衡,将A的左孩子右上旋
- RR:在A的右孩子的右子树插入导致A不平衡,将A的右孩子左上旋
- LR:在A的左孩子的右子树插入导致A不平衡,将A的左孩子的右孩子,先左上旋再右上旋
- RL:在A的右孩子的左子树插入导致A不平衡,将A的右孩子的左孩子,先右上旋再左上旋
- 查找效率分析
-
👩💻 高为h的平衡二叉树最少有几个结点——递推求解
假设以nh表示深度为h的平衡树中含有的最少结点数,则有n0=0,n1=1,n2=2,并且有
-
平衡二叉树最大深度为O(logn),平均查找长度/查找的时间复杂度为O(logn)
-
平衡二叉树的删除
具体步骤
- 删除结点(方法同“二叉排序树”)
- 若删除的结点是叶子,直接删
- 若删除的结点只有一个子树,用字数顶替删除位置
- 若删除的结点有两棵子树,用前驱(或后继)结点顶替,并转化为对前驱(或后继)结点的删除
- 从被删除结点向上回溯,找到最小不平衡子树。找不到就结束。
- 找到最小不平衡子树z下,y是结点z的高度最高的孩子节点,x是结点y的高度最高的孩子节点。
- 然后对以z为根的子树进行平衡调整(LL/RR/LR/RL)
- 如果不平衡向上传到,继续2
- 对最小不平衡子树的旋转可能导致树变矮,从而导致上层祖先不平衡(不平衡向上传递)
平衡二叉树删除操作时间复杂度=O(log2n)
红黑树
红黑树和平衡二叉树在查找、插入、删除的时间复杂度都是O(log2n)。但使用场景不同,
平衡二叉树:适用于以查为主、很少插入/删除的场景;
红黑树:适用于频繁插入、删除的场景,实用性更强。
推荐一个“帮手快乐”网站:Red/Black Tree Visualization (usfca.edu)https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
- 红黑树是二叉排序树
- 黑高——一个结点的“黑高”从某结点出发(不含该结点)到达任一空姐点的路径上黑节点总数
- 定义
- 每个结点都是红色,或者是黑色的
- 根节点是黑色的
- 叶节点(NULL结点、外部结点)均是黑色的
- 不存在两个相邻的红节点(即红节点的父节点和孩子节点均是黑色)
- 对每个结点,从该节点到任一叶节点的简单路径上,所含黑结点的数目相同
- 性质:
- 从根节点到叶节点的最长路径不大于最短路径的2倍
- 从n个内部结点的红黑树高度h≤2log2(n+1)
红黑树的插入
- 先查找,确定插入位置(原理同二叉排序树),插入新结点
- 新结点是根——染为黑色
- 新结点非根——染为红色 (保证对每个结点,从该节点到任一叶节点的简单路径上,所含黑结点的数目相同)
- 若插入新结点后依然满足红黑树定义,则插入结束
- 若插入新结点后不满足红黑树定义,需要调整(看新结点叔叔的脸色),使其重新满足红黑树定义
- 黑叔:旋转+染色
- LL型:右单旋,父换爷+染色
- RR型:左单旋,父换爷+染色
- LR型:左、右双旋,儿换爷+染色
- RL型:右、左双旋,儿换爷+染色
- 红叔:染色+变新
- 叔父爷染色,爷变为新节点
- 黑叔:旋转+染色
红黑树的删除
- 时间复杂度=O(log2n)
- 删除结点的处理方式和“二叉排序树的删除”一样
- 按2处理后,可能破坏“红黑树特性”,此时需要调整结点颜色、位置,使其再次满足“红黑树特性”