红黑树详解
来源:互联网 发布:程序员的成长之路 编辑:程序博客网 时间:2024/06/05 06:42
1972年由Rudolf Bayer发明的,当时被称为平衡二叉B树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的“红黑树”。
红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。
它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。
红黑树的五个性质:
1)每个结点要么是红的,要么是黑的。2)根结点是黑的。
3)每个叶结点,即空结点(NIL)是黑的。
4)如果一个结点是红的,那么它的俩个儿子都是黑的。
5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点
树的插入删除,会影响树的特性
红黑树操作:
插入节点为红色N,被插入的节点为P,P的父节点为G,P的叔叔节点为U
树的插入删除,会影响树的特性
插入:
1.插入节点的父亲节点为黑色,不会影响树的性能。所以不用改变。
2.插入节点的父亲节点为红色,会分成3中情况:
a)叔叔节点为红色。
无论N在P左右,P在G的左右。把G换成红色,把P、U换成黑色。然后把G当成插入点向上验证树的特性。
b)叔叔节点为黑色或者没有。
所有情况如下图
发生下面情况发生变色右旋(G变红,P变成红色)
发生下面情况发生变色左旋(G变红,P变成红色)
发生下面情况发生右旋和变色左旋情况
发生下面情况发生左旋和变色右旋情况.第二个图形中PN位置反了
删除:
1.删除节点没有子节点,直接删除。
2.删除节点有子节点。
a)删除节点的孩子节点是单支节点(没有孩子节点),或者前继(节点左边最大的节点)后继(节点右边最小的节点)为单节点。直接替换与换颜色,移除删除的。如下:R为要删除的节点,M是R右边最小值。
b)R为要删除的节点,M是R右边最小值。N是M的右节点。R与M位置与颜色互换。N替换R。
如果发生b)种情况。N的位置变化会影响红黑树的特性。
U节点为红色:
U、UL、UR都为黑色:
U、UR为黑,UL为红:
U为黑色、UR为红色:
jdk1.8 HashMap.TreeNode的部分代码详解
//排序新插入的数据 并返回root节点static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root, TreeNode<K,V> x) {//x为新插入的treenode x.red = true;//默认设置成[红] for (TreeNode<K,V> xp, xpp, xppl, xppr;;) { if ((xp = x.parent) == null) {//x的父节点为xp,如果xp为空,那么xp就是root,因为红黑树中只有root节点的父节点为null x.red = false; return x; } else if (!xp.red || (xpp = xp.parent) == null)//xp为黑,不影响树的特征,直接插入。 //x的祖父节点为null,xp为root,树高为1不影响性能。 return root; if (xp == (xppl = xpp.left)) {//在祖父节点左边的树。 if ((xppr = xpp.right) != null && xppr.red) {//父亲节点右边节点为红色。 xppr.red = false; xp.red = false; xpp.red = true; x = xpp;//检查祖父接单是否符合树的特性。进行下一次循环。 } else {//祖父节点右边节点为黑色或没有 if (x == xp.right) {//插入节点在父节点的右边 root = rotateLeft(root, x = xp);//左旋转, xpp = (xp = x.parent) == null ? null : xp.parent;//x为旋转后的子节点(原父亲节点),xp //x为旋转后的父节点(原子亲节点) } if (xp != null) { xp.red = false;//xp(原插入节点)设成黑 if (xpp != null) { xpp.red = true; root = rotateRight(root, xpp);//右旋 } } } } else {//在祖父节点右边的树。 if (xppl != null && xppl.red) {//父亲节点右边节点为红色。 xppl.red = false; xp.red = false; xpp.red = true; x = xpp;//检查祖父接单是否符合树的特性。进行下一次循环。 } else { if (x == xp.left) { root = rotateRight(root, x = xp); xpp = (xp = x.parent) == null ? null : xp.parent; } if (xp != null) { xp.red = false; if (xpp != null) { xpp.red = true; root = rotateLeft(root, xpp); } } } } } }//删除treeNode后 ,发生位置变化的节点,触发的tree 的排序static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root, TreeNode<K,V> x) { for (TreeNode<K,V> xp, xpl, xpr;;) { if (x == null || x == root) return root; else if ((xp = x.parent) == null) { x.red = false; return x; } else if (x.red) { x.red = false; return root; } else if ((xpl = xp.left) == x) {//x是P的左节点 if ((xpr = xp.right) != null && xpr.red) {//兄弟节点为 红 xpr.red = false; xp.red = true; root = rotateLeft(root, xp); xpr = (xp = x.parent) == null ? null : xp.right; } if (xpr == null) x = xp; else { TreeNode<K,V> sl = xpr.left, sr = xpr.right; if ((sr == null || !sr.red) && (sl == null || !sl.red)) { //xpr的孩子节点非红 xpr.red = true; x = xp; } else {//xpr的孩子节点至少有一个为红 if (sr == null || !sr.red) {//xpr的右孩子节点非红,那么左孩子节点一定是红 if (sl != null) sl.red = false; xpr.red = true; root = rotateRight(root, xpr); xpr = (xp = x.parent) == null ? null : xp.right; } if (xpr != null) { xpr.red = (xp == null) ? false : xp.red; if ((sr = xpr.right) != null) sr.red = false; } if (xp != null) { xp.red = false; root = rotateLeft(root, xp); } x = root; } } } else { // x是P的右节点。操作顺序相反 if (xpl != null && xpl.red) { xpl.red = false; xp.red = true; root = rotateRight(root, xp); xpl = (xp = x.parent) == null ? null : xp.left; } if (xpl == null) x = xp; else { TreeNode<K,V> sl = xpl.left, sr = xpl.right; if ((sl == null || !sl.red) && (sr == null || !sr.red)) { xpl.red = true; x = xp; } else { if (sl == null || !sl.red) { if (sr != null) sr.red = false; xpl.red = true; root = rotateLeft(root, xpl); xpl = (xp = x.parent) == null ? null : xp.left; } if (xpl != null) { xpl.red = (xp == null) ? false : xp.red; if ((sl = xpl.left) != null) sl.red = false; } if (xp != null) { xp.red = false; root = rotateRight(root, xp); } x = root; } } } } }
- 红黑树 详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树详解
- 红黑树原理详解
- React-Native之路上遇到的问题
- 自适应Simpson积分(近似求积分)
- 全站压缩
- 一滴水:关于Java容器类库概念及Map.put();方法的使用
- 重温python基础2:控制流
- 红黑树详解
- MySQL数据库备份还原(基于binlog的增量备份)
- 安卓工作室 android studio 的 汉化 美化 定制 Android studio's Chinesization beautification customization
- 单选按钮和复选框
- Unity3D数学基础(4)_ 简单的排序算法总结
- 洛谷P1429 平面最近点对(加强版)
- Android中的Selector的用法
- 下拉列表框
- 一看就懂系列之 由浅入深聊一聊php的垃圾回收机制