红黑树的插入操作

  1 package Tree;
  2
  3 import org.junit.Test;
  4
  5 class RedBlackTreeNode {
  6
  7     int key = 0;
  8     RedBlackTreeNode left = null;
  9     RedBlackTreeNode right = null;
 10     RedBlackTreeNode parent = null;
 11     // 色域,0表示黑色,1表示红色
 12     int color;
 13
 14     public RedBlackTreeNode(int key) {
 15         this.key = key;
 16     }
 17 }
 18
 19 /**
 20  * 红黑树的四条性质 1,树中的结点要么是红结点要么是黑结点 2,根结点以及叶子结点都是黑结点 3,红结点的父亲结点一定是黑结点
 21  * 4,同一层上的结点到叶子结点所经过的路径,黑高度相同,也就是路径上的黑结点个数相同
 22  *
 23  * @author jinfeng
 24  *
 25  */
 26 public class RedBlackTree {
 27
 28     public RedBlackTreeNode nil = new RedBlackTreeNode(-1);
 29
 30     // 红黑树的查找功能,返回结点的引用
 31     public RedBlackTreeNode redBlackTreeSearch(RedBlackTreeNode T, int number) {
 32
 33         if (T == nil || T.key == number)
 34             return T;
 35         if (number < T.key)
 36             return redBlackTreeSearch(T.left, number);
 37         else
 38             return redBlackTreeSearch(T.right, number);
 39
 40     }
 41
 42     // 在红黑树T中对结点x进行左旋转
 43     // 假设结点x的右结点不空
 44     public RedBlackTreeNode leftRatation(RedBlackTreeNode T, RedBlackTreeNode x) {
 45         // 1,将x的右结点的左子树y.left链接到x的右子树上
 46         RedBlackTreeNode y = x.right;
 47         x.right = y.left;
 48         if (y.left != nil)
 49             y.left.parent = x;
 50         // 说明x结点是根结点
 51         // 2,修改y结点的父指针以及左子树的指针
 52         y.parent = x.parent;
 53         if (x.parent == nil) {
 54             T = y;
 55             y.parent = nil;
 56         } else if (x.parent.left == x)
 57             x.parent.left = y;
 58         else
 59             x.parent.right = y;
 60         y.left = x;
 61         // 3,修改x结点的父指针
 62         x.parent = y;
 63         return T;
 64     }
 65
 66     // 在红黑树T中对结点x进行右旋转
 67     // 假设结点x的左结点不空
 68     public RedBlackTreeNode rightRatation(RedBlackTreeNode T, RedBlackTreeNode x) {
 69         // 1,将x的左结点的右子树y.right链接到x的左子树上
 70         RedBlackTreeNode y = x.left;
 71         x.left = y.right;
 72         if (y.right != nil)
 73             y.right.parent = x;
 74         // 说明x结点是根结点
 75         // 2,修改y结点的父指针以及右子树的指针
 76         y.parent = x.parent;
 77         if (x.parent == nil) {
 78             T = y;
 79             y.parent = nil;
 80         } else if (x.parent.right == x)
 81             x.parent.right = y;
 82         else
 83             x.parent.left = y;
 84         y.right = x;
 85         // 3,修改x结点的父指针
 86         x.parent = y;
 87         return T;
 88     }
 89
 90     // 将结点z插入到红黑树T中
 91     public RedBlackTreeNode redBlackTreeInsert(RedBlackTreeNode T,
 92             RedBlackTreeNode z) {
 93         // 树为空的情况
 94         if (T == null) {
 95             T = z;
 96             T.parent = nil;
 97             T.left = nil;
 98             T.right = nil;
 99             T.color = 0;
100             return T;
101         }
102         // 树非空的情况,假设所有节点都不相同,y始终记录x的父节点
103         RedBlackTreeNode y = null, x = T;
104         while (x != nil) {
105             y = x;
106             if (z.key < x.key)
107                 x = x.left;
108             else
109                 x = x.right;
110         }
111         if (z.key < y.key)
112             y.left = z;
113         else
114             y.right = z;
115         z.parent = y;
116         z.left = nil;
117         z.right = nil;
118         z.color = 1;
119         return redBlackTreeInsertFixup(T, z);
120     }
121
122     // 重新上色,以及进行旋转操作,以满足红黑树的性质
123     public RedBlackTreeNode redBlackTreeInsertFixup(RedBlackTreeNode T,
124             RedBlackTreeNode z) {
125         // y用来记录x结点的叔结点的位置
126         RedBlackTreeNode y = null;
127         while (z.parent.color == 1 && z != T) {
128             // 第一大类 : z的父亲结点是祖父结点的左孩子
129             if (z.parent == z.parent.parent.left) {
130                 y = z.parent.parent.right;
131                 // case 1: z的叔结点y颜色是红色的
132                 if (y.color == 1) {
133                     z.parent.color = 0;
134                     y.color = 0;
135                     z.parent.parent.color = 1;
136                     z = z.parent.parent;
137                 }
138                 // case 2: z的叔结点y的颜色是黑色的,同时z是z的父亲的右孩子
139                 // 注意: 从case 2可以转化到case 3,这两种情况并不是完全独立的
140                 else {
141                     if (z.parent.right == z) {
142                         z = z.parent;
143                         T = leftRatation(T, z);
144                     }
145                     // case 3: z的叔结点y的颜色是黑色的,同时z是z的父亲的左孩子
146                     z.parent.color = 0;
147                     z.parent.parent.color = 1;
148                     T = rightRatation(T, z.parent.parent);
149                 }
150             }
151             // 第二大类 : z的父亲结点是祖父结点的右孩子
152             else {
153                 y = z.parent.parent.left;
154                 // case 1: z的叔结点y颜色是红色的
155                 if (y.color == 1) {
156                     z.parent.color = 0;
157                     y.color = 0;
158                     z.parent.parent.color = 1;
159                     z = z.parent.parent;
160                 }
161                 // case 2: z的叔结点y的颜色是黑色的,同时z是z的父亲的左孩子
162                 // 注意: 从case 2可以转化到case 3,这两种情况并不是完全独立的
163                 else {
164                     if (z.parent.left == z) {
165                         z = z.parent;
166                         T = rightRatation(T, z);
167                     }
168                     // case 3: z的叔结点y的颜色是黑色的,同时z是z的父亲的右孩子
169                     z.parent.color = 0;
170                     z.parent.parent.color = 1;
171                     T = leftRatation(T, z.parent.parent);
172                 }
173             }
174         }
175         // 根结点的颜色可能会被赋值为红色,所以这里重新设置颜色
176         T.color = 0;
177         return T;
178     }
179
180     // 中序遍历红黑树T
181     public void inOrderRedBlackTree(RedBlackTreeNode T) {
182         if (T == nil)
183             return;
184         inOrderRedBlackTree(T.left);
185
186         System.out.println("key : " + T.key + " color : " + T.color
187                 + ": parent " + T.parent.key + ", left " + T.left.key
188                 + ", right " + T.right.key);
189         inOrderRedBlackTree(T.right);
190     }
191
192     @Test
193     public void test() {
194         // 在函数体内修改红黑树的头结点对象引用,必须同时将其返回,java语法
195         RedBlackTreeNode T = null;
196         RedBlackTreeNode treeNode = null;
197         int[] array = { 1, 2, 5, 7, 8, 11, 14, 15 };
198         // 模拟叶子结点,也就是哨兵
199         nil.color = 0;
200         for (int i = 0; i < array.length; ++i) {
201             treeNode = new RedBlackTreeNode(array[i]);
202             T = redBlackTreeInsert(T, treeNode);
203         }
204         inOrderRedBlackTree(T);
205         System.out.print(T.key);
206
207     }
208
209 }
时间: 2024-10-13 23:29:58

红黑树的插入操作的相关文章

红黑树(2) - 插入操作

1.插入介绍 首先以二叉排序树的方法增加节点并标记它为红色.(为何不是红色?因为如果设为黑色,就会导致根到叶子的所有路径中,有一条路径上会多出一个额外的黑节点,这个是很难调整的).但是,设为红色节点后,可能会导致出现两个连续红色节点的冲突,则可以通过重新着色和旋转来调整.具体的调整操作取决于其他临近节点的颜色. 下面分析一下插入新节点后可能对红黑树性质产生的影响: 性质1-节点是红色或黑色.和性质3-所有叶子都是黑色.这两条总是可以维持不变. 性质4-每个红色节点的两个子节点都是黑色.只在增加红

红黑树(3) - 删除操作

在本系列的前面两篇文章中,已经介绍了红黑树以及其插入操作.具体可参考下面两个链接: 红黑树(1) - 介绍 红黑树(2) - 插入操作 1.删除操作介绍 类似于插入操作,红黑树进行删除节点时,也使用重新着色以及旋转这两种方式,来维护它的属性.在插入操作中,我们主要是依靠检测叔节点的颜色来决定哪种场景.在删除操作中,我们使用检测兄弟的颜色,来决定是哪种场景. 在插入操作中,最常见的违反红黑树属性的一种情况是存在两个连续的红色节点.而在删除操作中,常见的情况是,当删除节点是黑色时,会影响从根节点到叶

图解集合7:红黑树概念、红黑树的插入及旋转操作详细解读

原文地址http://www.cnblogs.com/xrq730/p/6867924.html,转载请注明出处,谢谢! 初识TreeMap 之前的文章讲解了两种Map,分别是HashMap与LinkedHashMap,它们保证了以O(1)的时间复杂度进行增.删.改.查,从存储角度考虑,这两种数据结构是非常优秀的.另外,LinkedHashMap还额外地保证了Map的遍历顺序可以与put顺序一致,解决了HashMap本身无序的问题. 尽管如此,HashMap与LinkedHashMap还是有自己

红黑树的插入

一.红黑树的介绍 先来看下算法导论对R-B Tree的介绍: 红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black.通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的. 前面说了,红黑树,是一种二叉查找树,既然是二叉查找树,那么它必满足二叉查找树的一般性质.下面,在具体介绍红黑树之前,咱们先来了解下 二叉查找树的一般性质:1.在一棵二叉查找树上,执行查找.插入.删除等操作,的时间复杂度为O(

红黑树之插入

1.红黑树 (1).概念 i>每个结点不是红的就是黑的: ii>根结点为黑的: iii>红结点的孩子必为黑结点: iv>(除了根结点)任一结点不管通过什么路径,到达叶子节点的黑结点数目一定相同: 总结概括:一头一脚黑,黑同红不连:根为黑,到脚(叶子节点)的黑结点相同,红结点不相连: 2.递归--->一般先写if结束语句 化非递归------>用while()循环和栈; enum{RED, BLACK}; 这个枚举是有值得,分别为0.1: 3.红黑树与AVL树  AVL树

红黑树的删除操作详解

注:本文转载自博客园,博主原址:http://www.cnblogs.com/tongy0/p/5460623.html,感谢博主帮我弄清楚了红黑树删除操作,转载做收藏用. 红黑树的删除操作 1:节点命名约定 D表示要被删除的节点.即:取 Delete 的首字母: P 表示父节点.即:取 Parent 的首字母: S表示兄弟姐妹节点.即:取 Sibling的首字母: U表示叔伯节点.即:取Uncle的首字母: G表示祖父节点.即:取 Grandfather的首字母: L表示左树.即:取Left的

红黑树的插入与删除

红黑树(Red Black Tree) 是一种自平衡二叉查找树.红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能.红黑树可以在O(log n)时间内完成查找,插入和删除操作. 二叉搜索树可以看 二叉搜索树 AVL树可以看 AVL树的插入与删除 1. 红黑树的性质 红黑树的自平衡依赖于它的以下性质: 性质1. 结点是红色或黑色. 性质2. 根结点是黑色. 性质3. 每个结点节点(NIL结点,空结点,与其它二叉搜索树不同,红黑树将叶子结点的孩子

红黑树的插入和遍历时间复杂度分析

红黑树的插入和遍历时间复杂度分析 在平常的工作中,最常用的一种数据结构恐怕是std::map了.因此对其的时间复杂度分析是有必要的,编写程序时做到心中有底. 一.理论分析 在stl中std::map和std::set都采用红黑树的方式实现.我们知道插入一个元素到红黑树的时间为log(N),其中N为当前红黑树的元素个数,因此,采用插入方式构建元素个数为N的红黑树的时间复杂度为: log(1) + log(2) + log(N-1) = log((N-1)!) = Nlog(N) 那么采用迭代器遍历

说说红黑树——不谈操作,只讲理解

一.前言 ??这几天想学一学红黑树这种数据结构,于是上网找了很多篇博客,初看吓了一跳,红黑树竟然如此复杂.连续看了几篇博客后,算是对红黑树有了一些了解,但是它的原理却并不是特别理解.网上的博客,千篇一律的都是在叙述红黑树的操作,如何插入节点.删除节点,旋转.变色等,只关注如何正确构建一棵红黑树,但是却很少提及为什么这么做.这篇博客我就来记录一些我所知道的红黑树中比较重要的东西,以及谈一谈我的理解. ??我不会描述红黑树的具体实现,因为阅读红黑树具体实现的过程中,我发现这真的不是很重要,没有太大的