Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019-09-16:什么是红黑树?为什么要用红黑树? #147

Open
Moosphan opened this issue Sep 16, 2019 · 3 comments
Open

2019-09-16:什么是红黑树?为什么要用红黑树? #147

Moosphan opened this issue Sep 16, 2019 · 3 comments

Comments

@Moosphan
Copy link
Owner

No description provided.

@ASDbobo
Copy link

ASDbobo commented Sep 17, 2019

红黑树又叫平衡二叉树,所以要先了解什么是二叉树.为什么要用红黑树,我理解就是查找数据速度快,就是添加和修改数据麻烦,但一般对于用户来说,更多追求查找数据显示出来快.
网上都有介绍,百度看一下就行了,http://www.sohu.com/a/201923614_466939

@peiniwan
Copy link

二叉树的提出其实主要就是为了提高查找效率,比如我们常用的 HashMap 在处理哈希冲突严重时,拉链过长导致查找效率降低,就引入了红黑树。
我们知道,二分查找可以缩短查找的时间,但是它要求 查找的数据必须是有序的。每次查找、操作时都要维护一个有序的数据集,于是有了二叉查找树这个概念。

查找二叉树(BST)是一种特殊的二叉树,其任何节点中的值都会大于或者等于其左子树中存储的值并且小于或者等于其右子树中存储的值。

二叉查找树好的情况下是O(logN),最坏情况下是O(N),查找最大的次数是二叉树的高度。比如:将一个数组{1,2,3,4}依次插入树的时候,有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本,所以有了平衡二叉树。

平衡二叉树(AVL)
平衡二叉树的提出就是为了保证树不至于太倾斜,尽量保证两边平衡(旋转)。因此它的定义如下:

平衡二叉树要么是一棵空树
要么保证左右子树的高度之差不大于 1
子树也必须是一颗平衡二叉树

红黑树
红黑是一种自平衡的查找二叉树
和AVl区别:avl插入、删除操作,为了保持平衡需要旋转。适合用于插入与删除次数比较少,但查找多的情况。

红黑树:相对于要求严格的AVL树来说,它的旋转次数少,所以对于搜索,插入,删除操作较多的情况下,我们就用红黑树。

@Alex-Cin
Copy link

Alex-Cin commented Oct 1, 2019

我看了大概一天的红黑树, 总结一下吧, 如果有错误, 欢迎指正

java 的 HashMap, TreeMap, TreeSet, Linux 的虚拟内存管理;
了解红黑树之前, 先了解二叉搜索树:
1.. 左子树上所有结点的值均小于或等于它的根结点的值;
2.. 右子树上所有结点的值均大于或等于它的根结点的值;
但是这样的二叉树, 很有可能变成线性结构, 为了避免出现这样的情况, 产生了红黑树;

每个节点, 都包含5个属性:color, key, left, right 和 parent;
如果一个节点没有子节点, 或者没有父节点, 则其对应属性值为 NULL;
我们可以把这些 NULL 视为指向二叉搜索树的叶子节点指针, 外部指针;
把带关键字的节点视为树的内部节点;

一般红黑树必须是满足以下属性的二叉搜索树:
1.. 每个节点是红色, 或者是黑色;
2.. 根节点是黑色;
3.. NULL 节点是黑色的;
4.. 如果一个节点是红色的, 那么他的两个子节点都是黑色的;
5.. 每个节点到所有叶子节点, 所经过的黑色节点数量相同;
6.. 最长路径不会超过最短路径的 2 倍;

从某个节点 N 出发, 达到一个叶子节点, 经过任意一个简单路径, 其黑色节点的个数称之为黑高, 记为 bh;
红黑树必须满足, 任意一个节点, 到其任意一个叶子节点, 经过任意的简单路径, 其黑高相等;

左旋传会带上左父亲, 右旋转会带上右父亲;

插入操作

基本描述
要将红黑树当作一棵二叉查找树, 找到插入的位置;
将节点着色为红色(默认就是红色);
通过旋转和重新着色, 对其修正, 使之成为一棵新的红黑树;
因为新插入的节点, 肯定是叶子节点咯, 所以要满足[每个节点到所有叶子节点, 所经过的黑色节点数量相同];
接下来, 还要依次满足剩余所有的基本属性;

什么情况下需要旋转, 什么情况下不需要旋转?
如果新插入的当前节点的父节点, 是黑色的, 就不需要做任何操作;
如果新插入的当前节点的父节点, 是红色的, 就需要重新着色, 旋转;
红黑树调整的整体思想是, 将红色的节点移到根节点, 然后, 将根节点设为黑色;

调整红黑树
(1)当前节点是根节点, 直接设为黑色的;
(2)当前节点的父节点是黑色的, 无序任何操作;
(3)当前节点的父节点是红色的, 叔叔节点是红色的;
将父亲节点, 设为黑色;
将叔叔节点, 设为黑色;
将祖父节点, 设为红色;
将祖父节点, 设为新的当前节点, 继续判断;

(4)当前节点的父节点, 是红色的, 叔叔节点是 T.nil 节点或者是黑色的, 当前节点是父节点的右孩子;
将祖父节点设为红色;
将父节点设为黑色;
当前节点的父节点, 设为新的当前节点;
以当前节点, 为支点进行左旋, 继续判断;

(5)当前节点的父节点, 是红色的, 叔叔节点是 T.nil 节点或者是黑色的, 当前节点是父节点的左孩子;
将祖父节点设为红色;
将父节点设为黑色;
当前节点的父节点, 设为新的当前节点;
以当前节点, 为支点进行右旋, 继续判断;

删除操作

待删除的节点情况可以分为 3 种:
1.. 是叶子节点;
2.. 只有左子树或只有右子树;
3.. 有左子树和右子树;

调整红黑树
后继节点, 就是右子树上最小的节点;
前驱节点, 就是左子树上最大的节点;
先看待删除的节点的颜色, 再看兄弟节点的颜色, 先看远侄子再看近侄子, 最后看父亲节点的颜色;

case.. 待删除的节点, 是红色的, 没有子节点, 直接删除既可;

case.. 待删除的节点, 是红色的, 只有一个子节点, 子节点一定是黑色的, 父节点也一定是黑色的;
直接删除当前节点, 子节点替换当前节点, 设为黑色即可;

case.. 待删除的节点, 是红色的, 它有两个子树, 当然左右子树都是黑色的, 父节点是黑色的;
从待删除的右子树, 找到最小的节点;
待删除节点与右子树最小节点, 数值互换;
右子树最小节点作为新的待删除节点, 继续判断;

case.. 待删除的节点, 是黑色的, 只有一个子节点, 子节点是红色的;
直接删除当前节点, 子节点替换当前节点, 设为黑色即可;

case.. 待删除的节点, 是黑色的, 是父节点的左子树, 并且兄弟节点是红色的;
父节点和兄弟节点颜色互换, 以兄弟节点为支点, 左旋传, 继续判断;

case.. 待删除的节点, 是黑色的, 是父节点的左子树, 它的兄弟节点是黑色的, 远侄子是红色的;
父节点和兄弟节点颜色互换, 远侄子设为黑色, 删除当前节点, 以兄弟节点为支点, 左旋传即可;

case.. 待删除的节点, 是黑色的, 是父节点的左子树, 它的兄弟节点是黑色的, 近侄子是红色的;
兄弟节点和近侄子颜色互换, 以兄弟节点为支点, 右旋传, 继续判断;

case.. 待删除的节点, 是黑色的, 是父节点的左子树, 它的兄弟节点是黑色的, 两个侄子都是黑色的;
从待删除的右子树, 找到最小的节点;
待删除节点与右子树最小节点, 数值互换;
右子树最小节点作为新的待删除节点, 继续判断;

case.. 待删除的节点, 是黑色的, 是父节点的右子树, 并且兄弟节点是红色的;
父节点和兄弟节点颜色互换, 以兄弟节点为支点, 右旋传, 继续判断;

case.. 待删除的节点, 是黑色的, 是父节点的右子树, 它的兄弟节点是黑色的, 远侄子是红色的;
父节点和兄弟节点颜色互换, 远侄子设为黑色, 删除当前节点, 以兄弟节点为支点, 右旋转即可;

case.. 待删除的节点, 是黑色的, 是父节点的右子树, 它的兄弟节点是黑色的, 近侄子是红色的;
兄弟节点和近侄子颜色互换, 以兄弟节点为支点, 左旋传, 继续判断;

case.. 待删除的节点, 是黑色的, 是父节点的右子树, 它的兄弟节点是黑色的, 两个侄子都是黑色的;
从待删除的右子树, 找到最小的节点;
待删除节点与右子树最小节点, 数值互换;
右子树最小节点作为新的待删除节点, 继续判断;

case.. 待删除的节点, 是黑色的, 它的兄弟节点是黑色的, 它和兄弟节点都没有子节点;
父节点设为黑色, 兄弟节点设为红色, 删除当前节点即可;

参考

https://www.cnblogs.com/skywang12345/p/3245399.html
http://blog.chinaunix.net/uid-26548237-id-3480169.html
http://blog.csdn.net/u010367506/article/details/23962671
http://gengning938.blog.163.com/blog/static/1282253812011420103852696/
https://mp.weixin.qq.com/s/ilND8u_8HGSTSrJiMB4X8g

插入
https://blog.csdn.net/qq_36610462/article/details/83304175

删除
https://www.cnblogs.com/qingergege/p/7351659.html
https://www.cnblogs.com/gcheeze/p/11186806.html
https://my.oschina.net/u/3272058/blog/1914452
https://blog.csdn.net/qq_36610462/article/details/83304175

在线演示红黑树
https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
http://sandbox.runjs.cn/show/2nngvn8w
http://files.cnblogs.com/files/bbvi/RedBlackBinaryTree.rar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants