秋招对我好点!!!
1. 什么是二叉查找树(二叉排序树)?
二叉查找树的特性:
-
左子树上所有结点的值均小于或等于它的根结点的值
-
右子树上所有结点的值均大于或等于它的根结点的值
-
左、右子树也分别为二叉排序树
在二叉查找树中查找或插入一个数字,可以根据它跟根节点的大小关系进行判断。 这种方式运用了二分查找的思想。
但是插入的话,容易将二叉树退化成链表,所以引入红黑树这种可以保持相对平衡的树
在此之前,有必要提一下什么是二叉平衡树?
2. 什么是二叉平衡树?
二叉查找树的特性:
-
叶节点高度差的绝对值不超过1
-
左、右子树也分别为二叉平衡树
其中,AVL树是严格平衡的二叉树,要求节点左右子树高度差不能超过1;而红黑树要宽松一点,要求任何一条路径的长度不超过其他路径长度的2倍。
3. 什么是红黑树?
红黑树是一种自平衡的二叉查找树
红黑树的特性:
-
结点是红色或黑色
-
根结点是黑色
-
每个叶子结点都是黑色的空结点(NIL节点)
-
每个红色结点的两个子结点都是黑色(从每个叶子到根的所有路径上不能有两个连续的红色结点)
-
从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。
4. 如何保证红黑树的特性?
【变色】和【旋转】
旋转又分为**【左旋转】和【右旋转】**
变色:
为了重新符合红黑树的规则,尝试把红色结点变为黑色,或者把黑色结点变为红色。
例如:
(以下图片来源)
节点21和节点22连续出现了红色,不符合规则4,所以把节点22从红色变成黑色:
多出的黑色节点打破了规则5,所以发生连锁反应,需要继续把节点25从黑色变成红色:
此时仍然没有结束,因为节点25和节点27又形成了两个连续的红色节点,需要继续把节点27从红色变成黑色:
当然,这里的节点25不是根节点,否则违背了第2条约定!
左旋转:
逆时针旋转红黑树的两个节点,使得父节点被自己的右孩子取代,而自己成为自己的左孩子。
身为右孩子的Y取代了X的位置,而X变成了自己的左孩子。此为左旋转。(其中的节点a,b按照节点顺序排列下去)
右旋转:
顺时针旋转红黑树的两个节点,使得父节点被自己的左孩子取代,而自己成为自己的右孩子。
身为左孩子的Y取代了X的位置,而X变成了自己的右孩子。此为右旋转。
5. 如何保证红黑树特性的五种案例?
正所谓,兵来将挡,水来土掩。
对于某些特定的情况,红黑树的有特定的调整方法。
以下图片来源
局面1:新结点(A)位于树根,没有父结点。
这种局面,直接让新结点变色为黑色,规则2得到满足。同时,黑色的根结点使得每条路径上的黑色结点数目都增加了1,所以并没有打破规则5。
(黑色和红色不需要交替,只需要每条路径上的黑色节点相同,所以插入红色节点,看情况选择是否变色保证特性即可)
局面2:新结点(B)的父结点是黑色。
这种局面,新插入的红色结点B并没有打破红黑树的规则,所以不需要做任何调整。
局面3:新结点(D)的父结点和叔叔结点都是红色。
这种情况,根据约定,不能同时出现连续的两个红色节点,所以节点B需要变成黑色。凭空多出的黑色节点导致黑色节点数不相同,因此要修改A为红色,然而红色节点的子节点必须是黑色,所以最后将C改成黑色即可。
局面4:新结点(D)的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的右孩子,父结点(B)是祖父结点的左孩子。
以结点B为轴,做一次左旋转,使得新结点D成为父结点,原来的父结点B成为D的左孩子:
这样一来,进入了局面5。
局面5:新结点(D)的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的左孩子,父结点(B)是祖父结点的左孩子。
我们以结点A为轴,做一次右旋转,使得结点B成为祖父结点,结点A成为结点B的右孩子:
接下来,我们让结点B变为黑色,结点A变为红色:
经过上面的调整,这一局部重新符合了红黑树的规则。
6. 红黑树的应用(c++)?
map、set、multimap、multiset(其中multimap和multiset可以保存重复的元素)
总之,需要时刻记住!!!