首页 > 代码库 > 红黑树的插入操作
红黑树的插入操作
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 else109 x = x.right;110 }111 if (z.key < y.key)112 y.left = z;113 else114 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 // 中序遍历红黑树T181 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.color187 + ": parent " + T.parent.key + ", left " + T.left.key188 + ", right " + T.right.key);189 inOrderRedBlackTree(T.right);190 }191 192 @Test193 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 }
红黑树的插入操作
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。