红黑树和AVL树有什么区别?
红黑树 vs AVL
红黑树的查询性能略微逊色于AVL树,因为他比avl树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的avl树最多多一次比较,但是,红黑树在插入和删除上完爆avl树,avl树每次插入删除会进行大量的平衡度计算,而红黑树为了维持红黑性质所做的红黑变换和旋转的开销,相较于avl树为了维持平衡的开销要小得多
平衡二叉树的性质:
1、AVL树是自平衡二分搜索树
2、平衡二叉树
(1)对于任意一个节点,左子树和右子树的高度差不能超过为1。
(2)对于堆和线段二叉树来说,可以保证任意一个叶子节点相应的高度差不能超过1。
AVL树查找、插入和删除在平均和最坏情况下都是O(log n)。
下图为平衡二叉树
下图为不平衡二叉树
3、平衡因子
跟踪每个节点,对应的高度,这样才能判断是否平衡
标注节点的高度差,左子树减去右子树
“2”节点高度差为 0-0=0 ,左子树高度为0,右子树高度为0
“8”节点高度差为 3-1=2,左子树高度为3,右子树高度为1
“12”节点高度差为4-2= 2,左子树高度为4,右子树高度为2
4、什么时候维护平衡
在二分搜索树中要插入一个节点,需要从根节点一路下来,最终寻找到这个节点的插入位置,插入节点的位置都是叶子节点的位置。
28下来到33的左子树
由于新添加一个节点,才有可能导致二分搜索树不在满足平衡性,相应的不平衡节点,只有可能发送在插入的位置,向父亲节点去找,
因为插入新节点破坏了平衡性,高度就要更新,平衡因子就会大于1或者小于-1.
5、右旋转
左子树的高度比右子树的高度要高,高度差比1大
(1)首先将 x 的右子树变成以y节点根的子树,T3放一边,x.right =y
(2)在让y节点的左子树变成刚刚x的右子树所连接的T3,y.left=T3
(3)这里让x变成这个平衡二叉树的根节点。
左旋一样的道理
6、适用性:AVL查找效率高
如果你的应用中,搜索的次数远远大于插入和删除,那么选择AVL树,
应用:Windows NT内核中广泛存在
红黑树的性质:
-
节点是红色或黑色。
-
根节点是黑色。
如果根节点是2节点,就是黑色的节点
如果根节点是3节点,根节是c节点,依然是黑色节点
-
每一个叶子节点(最后的空节点)是黑色。
相当于红黑树定义空这样的节点本身就是黑色的
极端情况下,整棵树都空,这个空即是叶子节点又是黑色,定义他是黑色的。 -
如果一个节点是红色的,那么他的孩子节点都是黑色的
-
从任意一个节点到叶子节点,经过的黑色节点是一样的
2、红黑树是保持“黑平衡”的二叉树。
对于黑平衡是指,从根节点开始搜索,一直搜索到叶子节点,所经历的黑色节点的个数是一样的。、
黑平衡二叉树,严格意义上,不是平衡二叉树。
左右子树的高度差可能大于1。
时间复杂度是O(logn),最大高度:2logn
红黑树不会像二分搜索树一样退化为链表。
查找的时间上面会比AVL树慢一点,因为最大高度为2logn
添加操作和删除操作比AVL树要快一些
下面是添加一个元素
(1)如果三节点中间添加一个元素,先左旋转——》右旋转——》颜色翻转
(2)如果三节点添加比这两个元素还要小的元素,直接跳到——》右旋转——》颜色翻转
(3)如果三节点添加比这两个元素都要大的元素,直接跳到——》颜色翻转
3、维护的时间和AVL树一样:
都使用二分搜索树基本逻辑,新的节点添加进红黑树中,之后再进行红黑树性质维护,在维护完将根节点返回到递归,调用上层,从上一层角度再看是否还需要维护新的节点,以此类推。
红黑树性能总结
1、对于完全随机的数据,普通的二分搜索树很好用。
缺点:极端情况退化成链表(或者高度不平衡)
2、对于查询较多的使用情况,AVL树很好用。
红黑树牺牲平衡性(2logn高度)。
红黑树统计性能更优(综合增删改查所有操作)
有序底层TreeSet、TreeMap都是红黑树
应用
1、着名的Linux的的进程调度完全公平调度程序,用红黑树管理进程控制块,进程的虚拟内存区域都存储在一颗红黑树上,每个虚拟地址区域都对应红黑树的一个节点,左指针指向相邻的地址虚拟存储区域,右指针指向相邻的高地址虚拟地址空间;
2、IO多路复用的epoll的的的实现采用红黑树组织管理的的的sockfd,以支持快速的增删改查;
3、Nginx的的的中用红黑树管理定时器,因为红黑树是有序的,可以很快的得到距离当前最小的定时器;
4、Java的的的中TreeMap中的中的实现;