1、结点java
package com.company.RedBlackTree; /** * Created by jiayi on 2016/10/29. */ enum colors{ red,black; }; public class RedBlackTreeNode implements Cloneable { colors color; int key; RedBlackTreeNode left; RedBlackTreeNode right; RedBlackTreeNode p; int depth; public RedBlackTreeNode clone() throws CloneNotSupportedException{ //浅拷贝 RedBlackTreeNode cloned = (RedBlackTreeNode) super.clone(); return cloned; } RedBlackTreeNode(){ color = colors.black; key = 0; left = null; right = null; p = null; depth = 0; } RedBlackTreeNode(int key){ color = colors.black; this.key = key; left = null; right = null; p = null; depth = 0; } public boolean equals(RedBlackTreeNode x){ if(x.key == key && x.color == color && x.left == left && x.right == right){ return true; }else { return false; } } }
2、红黑树的插入(RBInsert)、删除(RBDelete)、链接(RBJoin)node
package com.company.RedBlackTree; import java.util.LinkedList; import java.util.Queue; import java.util.Map; import java.util.HashMap; /** * Created by jiayi on 2016/10/29. */ public class RedBlackTree implements Cloneable{ public RedBlackTreeNode nil; public RedBlackTreeNode root; public int N;
public RedBlackTree(){ nil = new RedBlackTreeNode(); root = nil; } public RedBlackTree(RedBlackTreeNode root){ this.root = root; nil = new RedBlackTreeNode(); } public void test(int[] a){ for( int i = 0 ; i < a.length ; i++ ){ RedBlackTreeNode temp = new RedBlackTreeNode(a[i]); RBInsert(temp); bfsTree(); //Print(); } /*bfsTree(); RedBlackTreeNode temp = RBSearch(root,a[5]); RBDelete(temp); bfsTree();*/ //Print(); } // 计算某节点在整棵树的第几层(ROOT为第1层) public int getLevelOfFullTree(RedBlackTreeNode node) { int depth = 0;
RedBlackTreeNode t = node; while (t != nil) { depth++; t = t.p; } return depth; } // 树形本层节点打印 private void printTreeLevel(String[] nodes) { System.out.print("\n|"); for (int j = 0; j < nodes.length; j++) { if (nodes[j] == null||nodes[j].length() == 0) { // 打印两位数字的占位符 System.out.printf("---"); } else { // 打印节点 System.out.printf("%3s", nodes[j]); // 重置数组 nodes[j] = ""; } } System.out.print("|");
}算法
public void bfsTree() { System.out.print("\n------------------ 树形打印开始 ------------------"); if (this.root.equals( nil)) { System.out.print("\n树为pw"); return; } // 二叉树的高度 int maxLevel = getDepth(root); // 满二叉树时的总结点数 int fullTotal = (int) Math.pow(2, maxLevel) - 1; // 水平数组 //int[] nodes = new int[fullTotal]; String[] nodes = new String[fullTotal]; // 上一个节点的层次 int prevLevel = 1; // 每层的起始下标 int start = 0; // 每一层的元素的间距 int stepSize = 0; // 广度优先遍历 Queue<RedBlackTreeNode> queue = new LinkedList<>(); queue.offer(root); RedBlackTreeNode node = nil; // 若是用数组存储二叉树,indexMap中存储各节点对应数组的下标 Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>(); while (!queue.isEmpty()) { // 删除队列头结点 node = queue.poll(); // 某节点在整棵树的第几层(ROOT为第1层) int levelOfFullTree = getLevelOfFullTree(node); // 若是当前深度比前一个节点的尝试大,则开始的新一层的节点访问 if (levelOfFullTree > prevLevel) { // 打印层次的节点 printTreeLevel(nodes); } // 计算新的层次的开始下标与步长 start = (int) Math.pow(2, maxLevel - levelOfFullTree) - 1; stepSize = (int) Math.pow(2, maxLevel - levelOfFullTree + 1); // System.out.print("\n" + "start:" + start + ",stepSize:" + stepSize); // 记录节点的下标 int idx = -1; if (node == root) { indexMap.put(node.key, 1); idx = 1; } else{ if (node == node.p.left) { idx = 2 * indexMap.get(node.p.key) - 1; } else if (node == node.p.right) { idx = 2 * indexMap.get(node.p.key); } indexMap.put(node.key, idx); } // 计算映射到水平数组的位置 int y = start + (idx - 1) * stepSize; String c; if(node.color == colors.black){ c = "b"; }else { c = "r"; } nodes[y] = String.valueOf(node.key) + c ; // System.out.print("\n" + "node.value:" + node.value + ",y:" + y); // 将节点的左孩子加入队列 if (!node.left.equals( nil)) { queue.offer(node.left); } // 将节点的右孩子加入队列 if (!node.right.equals( nil)) { queue.offer(node.right); } // 保留层次数,为下次循环使用 prevLevel = levelOfFullTree; } // 打印最底层的节点,由于while的推出,最底层次的节点没有打印,在这里单独打印 this.printTreeLevel(nodes); System.out.print("\n------------------ 树形打印结束 ------------------"); } // 计算以某节点为根的树的深度(从1开始) public int getDepth(RedBlackTreeNode node) { if (node.equals( nil)) { return 0; } return 1 + Math.max(this.getDepth(node.left), this.getDepth(node.right)); } /** * 二叉树的广度优先遍历,按照树形打印此树 * * * 算法用到的参数: * 1:二叉树的最大深度。 * 2:每一个节点在二叉树中的层次Level,从1开始。 * 3:每一个节点在该层中的序号indexOfLevel,从1开始。 * 注: * (1)Level和indexOfLevel能够在广度优先遍历时用计数器实现。 * (2)Level和indexOfLevel也能够在向树中插入新节点时,初始化到节点中。 * 若是用数组存储二叉树,假设父节点下标为i,则其左孩子的下标是2*i-1,右孩子的下标是2*i+1。 * * 算法基本思路: * (1):建立一个水平数组,水平数组的长度为 "满二叉树" 中的节点总数,将二叉树的全部节点,按满二叉树的样子,投影到水平数组上,每一个节点在水平数组中都对就一个位置。 * (2):咱们总结一下,对于每个层级,映射到水平数组后,第一个节点的开始下标=s,本层任意相邻节点的步长(间距)=d,若是下所示 * 层级 起始下标 步长 * 1 2^3-1=7 2^4=16 * 2 2^2-1=3 2^3=8 * 3 2^1-1=1 2^2=4 * 4 2^0-1=0 2^1=2 * (3):有了以上数据,咱们能够计算出,任意一层,任意一节点在水平数组中的下标, * 下标=起始下标+(该节点所在层次-1)*步长 * (4):OK,每一次每一个节点的位置肯定了,树形图天然也肯定了。 * * 另: * 若是想要让输出特别规矩,咱们必须: * 1:先肯定每一个节点的值(即输出的内容)最多占多少个字符宽度,假设为flength。 * 在输出树的过程当中,不论遇到空值仍是有值,都格式化输出,长度不足flength的,用空格补齐。 * 2:能够适当的将水平数组扩大一倍,这样每层中的各节点之间的距离拉长了,最终看到的结果是整个树水平放大了。 * */ private RedBlackTreeNode RBSearch(RedBlackTreeNode x, int k){ while (x != nil){ if(x.key > k){ return RBSearch(x.left,k); }else if(x.key < k){ return RBSearch(x.right,k); } else return x; } return nil; } private void LeftRotate(RedBlackTreeNode x){ // 假设x.right != Nil RedBlackTreeNode y = x.right; //将y设为新的子树根节点 x.right = y.left; if(y.left != nil){ y.left.p = x; } if(x.p.right == x){ x.p.right = y; y.p = x.p; }else if(x.p.left == x){ x.p.left = y; y.p = x.p; }else{ y.p = nil; root = y; } //x成为y的左孩子 y.left = x; x.p = y; //y的左孩子成为x的右孩子 } private void RightRotate(RedBlackTreeNode y){ //使x成为新的根节点 RedBlackTreeNode x = y.left; y.left = x.right; if(x.right != nil){ y.left.p = y; } if(y.p.left == y){ y.p.left = x; x.p = y.p; }else if(y.p.right == y){ y.p.right = x; x.p = y.p; }else{ root = x; x.p = nil; } // y成为x的右孩子 y.p = x; x.right = y; //x的右孩子变成y的左孩子 //y.left = x.right; } private void RBInsert(RedBlackTreeNode z){ RedBlackTreeNode y = nil; RedBlackTreeNode x = root; while (x != nil){ y = x; if(z.key < x.key){ x = x.left; }else{ x = x.right; } } z.p = y; if(y == nil){ root = z; }else if(z.key < y.key){ y.left = z; }else{ y.right = z; } z.right = nil; z.left = nil; z.color = colors.red; RBInsertFixup(z); ++N; } private void RBInsertFixup(RedBlackTreeNode z){ while (z.p.color == colors.red){ //因为z的父节点为红,z也为红,故须要调整 //首先想把z的父节点set为红--> z.p的分支不知足性质5 --> 将z.p.p set为黑,且将z.uncle set为红 if(z.p == z.p.p.left){//若z.p是z.p.p的左孩子 RedBlackTreeNode y = z.p.p.right;//z的叔节点 if(y.color == colors.red){//case 1 : 若是z的叔节点是红色(与z的父节点颜色同样) z.p.color = colors.black; y.color = colors.black; z.p.p.color = colors.red; z = z.p.p; ++z.depth; }else if(z == z.p.right){ // case 2 : 若是z的叔节点是黑色,且z是右孩子 z = z.p; LeftRotate(z);//左旋,使得红色节点z上移 } z.p.color = colors.black;//case 3 if(z.p != nil) { z.p.p.color = colors.red; RightRotate(z.p.p); } }else{//若z.p是z.p.p的右孩子 RedBlackTreeNode y = z.p.p.left; if(y.color == colors.red){//case 1 : 若是z的叔节点是红色(与z的父节点颜色同样) z.p.color = colors.black; y.color = colors.black; z.p.p.color = colors.red; z = z.p.p; }else { if (z == z.p.left) { // case 2 : 若是z的叔节点是黑色,且z是左孩子 z = z.p; RightRotate(z);//左旋,使得红色节点z上移 } z.p.color = colors.black;//case 3\ if(z.p != nil) { z.p.p.color = colors.red; LeftRotate(z.p.p); } } } } root.color = colors.black; root.p = nil; } private void RBDelete(RedBlackTreeNode z){ RedBlackTreeNode y = z; colors yOriginalColor = y.color; RedBlackTreeNode x = nil; if(z.left == nil){ //只有右边节点 x = z.right; RBTranlant(z,z.right); }else if(z.right == nil){//只有左边节点 x = z.left; RBTranlant(z,z.left); }else{//左右都有节点 y = TreeMinimum(z.right);//z的后继 yOriginalColor = y.color; x = y.right; if(y.p == z){//z.right 就是z的后继 x.p = y ;//为啥? }else{ //后继是y //先用y.right代替y RBTranlant(y,y.right); //再用y代替z y.right = z.right; y.right.p = y; } RBTranlant(z,y); y.left = z.left; y.left.p = y; y.color = z.color; } if(yOriginalColor == colors.black){ //当z有一个儿子时,y就是z,x就是z的儿子 //已知y原为黑色,即z原来为黑色。可是 //z.child(也就是x)替换z后,可能会改变z位置(也就是如今的x)的黑高,故须要调整x // 若x是红色,那么有可能和原来z.p构成双红,以及会破坏x处黑高 --> 把x设置为黑色便可 // 若x是黑色,会减少黑高,须要调整 //当z有两个儿子时,y是z的后继,x是y.right //z被y替换,已知y是黑色,则会改变z位置(如今y)的黑高。 //调整: //a.若x是红色,那么有可能和原来y.p构成双红,以及会破坏x处黑高 --> 把x设置为黑色便可 //b.若x是黑色,因为y的上移,本分支黑高被破坏,须要调整 // 2.若z原来是红色,则y被重置为红色。x替换y后,如今x位置处的性质被破坏 RBDeleteFixup(x); } } private void RBDeleteFixup(RedBlackTreeNode x){ while (x != root && x.color == colors.black){ // bfsTree(); RedBlackTreeNode w = nil; if(x == x.p.left){ //x是一个左孩子 w = x.p.right;//x的兄弟节点 if(w.color == colors.red) { //case 1 colors tempXP = x.p.color; x.p.color = w.color; w.color = tempXP; LeftRotate(x.p); w = x.p.right; }else{ if(w.right.color == colors.black){ if(w.left.color == colors.black){//case 2 w.color = colors.red; x = x.p; --x.depth; }else { // case 3 colors temp = w.color; w.color = w.left.color; w.left.color = temp; RightRotate(w); w = x.p.right; } }else{// case 4 w.color = x.p.color; x.p.color = colors.black; --x.p.depth; ++w.depth; w.right.color = colors.black; LeftRotate(x.p); x =root; } } }else{ w = x.p.left;//x的兄弟节点 if(w.color == colors.red) { //case 1 colors tempXP = x.p.color; x.p.color = w.color; w.color = tempXP; RightRotate(x.p); w = x.p.left; }else{ if(w.left.color == colors.black){ if(w.right.color == colors.black){//case 2 w.color = colors.red; x = x.p; }else { // case 3 colors temp = w.color; w.color = w.right.color; w.right.color = temp; LeftRotate(w); w = x.p.left; } }else{// case 4 w.color = x.p.color; x.p.color = colors.black; w.left.color = colors.black; RightRotate(x.p); x =root; } } } } x.color = colors.black; } private void RBTranlant(RedBlackTreeNode u,RedBlackTreeNode v){//用v替换u if(u == u.p.right){//u是u.p的右孩子 u.p.right = v; v.p = u.p; }else if( u == u.p.left ){//u是u.p的左孩子孩子 u.p.left = v; v.p = u.p ; }else {//u是根节点 v.p = nil; root = v; } } public RedBlackTree RBJoin(RedBlackTree T1, RedBlackTree T2, int x) throws CloneNotSupportedException { RedBlackTreeNode x_root = new RedBlackTreeNode(x); x_root.right = T1.root; T1.root.p = x_root; x_root.left = T2.root; T2.root.p = x_root;
int x_N = Math.max(T1.N,T2.N); RedBlackTree newTree = new RedBlackTree(x_root); newTree.N = x_N; T1.nil = newTree.nil; T2.nil = newTree.nil; x_root.p = newTree.nil; return newTree; } private RedBlackTreeNode TreeMinimum(RedBlackTreeNode x){//获得最小值 while (x.left != nil){ x = x.left; } return x; } private RedBlackTreeNode TreeMaximum(RedBlackTreeNode x){//获得最大值 while (x.right != nil){ x = x.right; } return x; }
}数组