JAVA红黑树

概念:每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色,提高二叉树的查找性能;

特性:

性质1. 节点是红色或黑色。

  性质2. 根是黑色。

  性质3. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

  性质4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

 

性能:O(log n)的时间之外,每次插入或删除需要O(log n)的空间。
实现:

JAVAQueue:用linkedlist写的队列

[java]  view plain copy
  1. import java.util.LinkedList;  
  2.   
  3. public class JavaQueue {  
  4.   
  5.     /** 
  6.      * @param args 
  7.      */  
  8.     private LinkedList list = new LinkedList();  
  9.   
  10.     public void push(Object v) {  
  11.         list.addFirst(v);  
  12.     }  
  13.     public Object pop() {  
  14.         return list.removeFirst();  
  15.     }  
  16.   
  17.     public Object get() {  
  18.         return list.removeLast();  
  19.     }  
  20.   
  21.     public boolean isEmpty(){  
  22.         return list.isEmpty();  
  23.     }  
  24.   
  25. }  

 

JAVAStack:用linkedlist写的堆栈

              

[java]  view plain copy
  1. import java.util.ArrayList;  
  2. import java.util.HashMap;  
  3. import java.util.LinkedList;  
  4. import java.util.Map;  
  5.   
  6. import com.sun.xml.internal.bind.v2.schemagen.xmlschema.List;  
  7.   
  8. public class JavaStack {  
  9.     private LinkedList list = new LinkedList();  
  10.     public void push(Object v) {  
  11.         list.addFirst(v);  
  12.     }  
  13.     public Object pop(){  
  14.         return list.removeFirst();  
  15.     }  
  16.     public Object top(){  
  17.         return list.getFirst();  
  18.     }  
  19.     public boolean  IsNull(){  
  20.         if(list.size()==0return true;  
  21.         else return false;  
  22.     }  
  23.     /*public static void main(String[] args) { 
  24.         // TODO Auto-generated method stub 
  25.         JavaStack stack=new JavaStack(); 
  26.         for(int i=0;i<10;i++) 
  27.         { 
  28.             stack.push(i); 
  29.         } 
  30.             System.out.println(stack.top()); 
  31.             stack.pop(); 
  32.             System.out.println(stack.top()); 
  33.         Map map=new HashMap(); 
  34.         A a=new A(); 
  35.         A b=new A(); 
  36.         A c=new A(); 
  37.         int i=0; 
  38.         map.put(i, a); 
  39.         map.put(i++, b); 
  40.         map.put(i++, c); 
  41.     } 
  42. */  
  43. }  

TreeNode:定义的节点类

               

[java]  view plain copy
  1. public class TreeNode {  
  2.     //应该包含五个域,left,right,p,key,color;  
  3.     TreeNode leftNode;//指示左结点  
  4.     TreeNode rightNode;//指示右结点  
  5.     TreeNode pNode;//指示父结点或者NIL(T)哨兵结点  
  6.     int key;//结点的值  
  7.     int color;//其中0表示红,1表示黑  
  8.     public TreeNode getLeftNode() {  
  9.         return leftNode;  
  10.     }  
  11.     public void setLeftNode(TreeNode leftNode) {  
  12.         this.leftNode = leftNode;  
  13.     }  
  14.     public TreeNode getRightNode() {  
  15.         return rightNode;  
  16.     }  
  17.     public void setRightNode(TreeNode rightNode) {  
  18.         this.rightNode = rightNode;  
  19.     }  
  20.     public TreeNode getPNode() {  
  21.         return pNode;  
  22.     }  
  23.     public void setPNode(TreeNode node) {  
  24.         pNode = node;  
  25.     }  
  26.     public int getKey() {  
  27.         return key;  
  28.     }  
  29.     public void setKey(int key) {  
  30.         this.key = key;  
  31.     }  
  32.     public int getColor() {  
  33.         return color;  
  34.     }  
  35.     public void setColor(int color) {  
  36.         this.color = color;  
  37.     }  
  38.     //默认构造函数  
  39.     public TreeNode(TreeNode leftNode,TreeNode rightNode,TreeNode pNode,int  key,int color){  
  40.         this.leftNode=leftNode;  
  41.         this.rightNode=rightNode;  
  42.         this.pNode=pNode;  
  43.         this.key=key;  
  44.         this.color=color;  
  45.     }  
  46. }  

TestRBT类:主要功能实现

              

[java]  view plain copy
  1. import javax.swing.JOptionPane;  
  2. import javax.swing.text.DefaultEditorKit.InsertBreakAction;  
  3.   
  4. import sun.management.counter.Variability;  
  5.   
  6. import com.sun.org.apache.regexp.internal.recompile;  
  7. import com.sun.org.apache.xml.internal.security.Init;  
  8.   
  9. public class TestRBT {  
  10.   
  11.     /** 
  12.      * @param args 
  13.      */  
  14.     public static void main(String[] args) {  
  15.         // TODO Auto-generated method stub  
  16.         // 1.建立一棵树,并进行初始化,也可通过插入节点进行建树  
  17.         // TreeNode[] node = new TreeNode[23];  
  18.         // 插入结点操作  
  19.         TreeNode nil = new TreeNode(nullnullnull, -11);//设定哨兵节点  
  20.         creatTree(nil);// 通过插入结点创建树,并以哨兵节点的父指针指向根节点  
  21.         showTree(nil.pNode, nil);// 展示插入建树后的结果  
  22.         deleteTree(nil, 8);// 删除节点,删除的节点也可从外部传入  
  23.         System.out.println("删除结点后:");  
  24.         showTree(nil.pNode, nil);// 展示删除树结点的结果  
  25.     }  
  26.   
  27.     public static void initTree(TreeNode node, TreeNode nil) {  
  28.         //初始化构造树int[] a={1,2,5,7,8,11,14,15,4}  
  29.         TreeNode tempnode = new TreeNode(nil, nil, nil, -11);  
  30.         node.leftNode = new TreeNode(nil, nil, node, 20);  
  31.         node.rightNode = new TreeNode(nil, nil, node, 141);  
  32.   
  33.         tempnode = node.leftNode;  
  34.         tempnode.leftNode = new TreeNode(nil, nil, tempnode, 11);  
  35.         tempnode.rightNode = new TreeNode(nil, nil, tempnode, 71);  
  36.   
  37.         tempnode = tempnode.rightNode;  
  38.         tempnode.leftNode = new TreeNode(nil, nil, tempnode, 50);  
  39.         tempnode.rightNode = new TreeNode(nil, nil, tempnode, 80);  
  40.   
  41.         tempnode = node.rightNode;  
  42.         tempnode.rightNode = new TreeNode(nil, nil, tempnode, 150);  
  43.         /* 
  44.          * int i = 2; while (i < 23) { if ((i == 2) || (i == 3) || (i == 4) || 
  45.          * (i == 6) || (i == 7) || (i == 9) || (i == 11) || (i == 12) || (i == 
  46.          * 14) || (i == 17) || (i == 18) || (i == 19) || (i == 20) || (i == 22)) 
  47.          * node[i] = new TreeNode(nil, nil, nil, i, 1); i++; } // 赋值 
  48.          * node[7].setLeftNode(node[4]); node[7].setRightNode(node[11]); 
  49.          * node[4].setLeftNode(node[3]); node[4].setRightNode(node[6]); 
  50.          * node[4].setPNode(node[7]); node[3].setLeftNode(node[2]); 
  51.          * node[3].setPNode(node[4]); node[2].setPNode(node[3]); 
  52.          * node[6].setPNode(node[4]); 
  53.          *  
  54.          * node[11].setLeftNode(node[9]); node[11].setRightNode(node[18]); 
  55.          * node[11].setPNode(node[7]); 
  56.          *  
  57.          * node[18].setLeftNode(node[14]); node[18].setRightNode(node[19]); 
  58.          * node[18].setPNode(node[11]); 
  59.          *  
  60.          * node[14].setLeftNode(node[12]); node[14].setRightNode(node[17]); 
  61.          * node[14].setPNode(node[18]); 
  62.          *  
  63.          * node[19].setRightNode(node[22]); node[19].setPNode(node[18]); 
  64.          *  
  65.          * node[22].setLeftNode(node[20]); node[22].setPNode(node[19]); 
  66.          *  
  67.          * node[12].setPNode(node[14]); node[17].setPNode(node[14]); 
  68.          * node[20].setPNode(node[22]); // show(node); 
  69.          *  
  70.          */  
  71.     }  
  72.   
  73.     public static void showTree(TreeNode node, TreeNode nil) {  
  74.         // 中序循环遍历树  
  75.         /* 
  76.          * JavaStack stack = new JavaStack(); // 将根结点输入栈中 while (node != nil || 
  77.          * !stack.IsNull()) { if (node != nil) { stack.push(node); node = 
  78.          * node.leftNode; } else { TreeNode tempnode = (TreeNode) stack.pop(); 
  79.          * System.out.print(tempnode.key+" " ); if (tempnode.rightNode != nil) 
  80.          * node = tempnode.rightNode; } } 
  81.          */  
  82.         // 层次遍历,分别打印出树的根结点,不用递归用循环提高效率  
  83.         JavaQueue queue = new JavaQueue();  
  84.         queue.push(node);// 将根结点输入栈中  
  85.         while (!queue.isEmpty()) {//队列不为空则出队列,继续添加新节点  
  86.             /**/  
  87.             TreeNode tempnode = (TreeNode) queue.get();  
  88.             int key = tempnode.key;  
  89.             StringBuffer str = new StringBuffer();//通过StringBuffer进行输出  
  90.             str.append("key:" + key);  
  91.             if (tempnode.color == 0) {  
  92.                 str.append(" color:红色");  
  93.             } else {  
  94.                 str.append(" color:黑色");  
  95.             }  
  96.             if (tempnode.leftNode != nil && tempnode.leftNode != null) {  
  97.                 str.append(" lefttree:" + tempnode.leftNode.key);  
  98.                 queue.push(tempnode.leftNode);  
  99.             }  
  100.   
  101.             if (tempnode.rightNode != nil) {  
  102.                 str.append(" righttree:" + tempnode.rightNode.key);  
  103.                 queue.push(tempnode.rightNode);  
  104.             }  
  105.             System.out.println(str.toString());  
  106.         }  
  107.     }  
  108.   
  109.     public static void leftRotate(TreeNode xnode, TreeNode nil) {  
  110.         //左旋转的实际为改变节点的前趋后继,三个节点,当前节点,当前节点的右节点,当前节点右节点的左节点  
  111.         TreeNode yNode = xnode.rightNode;// 设置右孩子为y结点  
  112.         xnode.rightNode = yNode.leftNode;  
  113.         if (yNode.leftNode != nil)  
  114.             yNode.leftNode.pNode = xnode;  
  115.         yNode.pNode = xnode.pNode;  
  116.         if (xnode.pNode == nil) {  
  117.             nil.pNode = yNode;  
  118.         } else if (xnode == xnode.pNode.leftNode) {  
  119.             xnode.pNode.leftNode = yNode;  
  120.         } else {  
  121.             xnode.pNode.rightNode = yNode;  
  122.         }  
  123.         yNode.leftNode = xnode;  
  124.         xnode.pNode = yNode;  
  125.     }  
  126.   
  127.     public static void rightRotate(TreeNode xnode, TreeNode nil) {  
  128.         TreeNode yNode = xnode.leftNode;// 设置左孩子为y结点  
  129.         xnode.leftNode = yNode.rightNode;  
  130.         if (yNode.rightNode != nil) {  
  131.   
  132.             yNode.rightNode.pNode = xnode;  
  133.         }  
  134.         yNode.pNode = xnode.pNode;  
  135.         if (xnode.pNode == nil) {  
  136.             nil.pNode = yNode;  
  137.         } else if (xnode == xnode.pNode.rightNode) {  
  138.             xnode.pNode.rightNode = yNode;  
  139.         } else {  
  140.             xnode.pNode.leftNode = yNode;  
  141.         }  
  142.         yNode.rightNode = xnode;  
  143.         xnode.pNode = yNode;  
  144.     }  
  145.   
  146.     public static void InsertTreeNode(int i, TreeNode nil) {  
  147.         TreeNode newnode = new TreeNode(nil, nil, nil, i, 0);// 设置新插入结点初始值为i  
  148.         TreeNode tempnode = new TreeNode(nil, nil, nil, -10);// 设置比较结点的父结点  
  149.         TreeNode recnode = new TreeNode(nil, nil, nil, -10);// 设置一个循环树结点  
  150.         // 执行查找过程,找到相应的位置并进行插入,随后进行红黑性质的插入调整  
  151.         recnode = nil.pNode;  
  152.         if (recnode == null) {  
  153.             nil.pNode = newnode;  
  154.             newnode.color = 1;  
  155.         } else {  
  156.             while (recnode != nil) {  
  157.                 tempnode = recnode;  
  158.                 if (i < recnode.key) {  
  159.                     recnode = recnode.leftNode;  
  160.                 } else {  
  161.                     recnode = recnode.rightNode;  
  162.                 }  
  163.             }  
  164.             newnode.pNode = tempnode;  
  165.             if (newnode.key < tempnode.key) {  
  166.                 tempnode.leftNode = newnode;  
  167.             } else {  
  168.                 tempnode.rightNode = newnode;  
  169.             }  
  170.             // 执行修补程序  
  171.             InsertTreeNodeFixup(nil, newnode);  
  172.         }  
  173.     }  
  174.   
  175.     public static void InsertTreeNodeFixup(TreeNode nil, TreeNode newnode) {  
  176.         TreeNode tempnode = new TreeNode(nil, nil, nil, -10);  
  177.         /*执行插入主要解决红红冲突,具体情况有三种,注意插入的结点默认均为红色 
  178.          * 1.newnode 的叔叔为红,即将其父,叔结点均置为黑 
  179.          * 2.newnode 的叔叔是黑,newnode为父结点的右孩子 
  180.          * 3.newnode 的叔叔是黑,newnode为父结点的左孩子 
  181.          * 2,3的解决办法是先进行一次相应方向的旋转(左子树即左转,右子树即右转),然后将newnode设为祖父结点, 
  182.          * 进行相应的反方向转动,最后设置根结点值为黑色 
  183.          * 插入操作可通过两次旋转彻底解决平衡问题 
  184.         */  
  185.         while (newnode.pNode.color == 0) {  
  186.             if (newnode.pNode == newnode.pNode.pNode.leftNode) {  
  187.                 tempnode = newnode.pNode.pNode.rightNode;// 叔父结点为爷爷的左子树  
  188.                 if (tempnode.color == 0) {// 叔父结点为红  
  189.                     newnode.pNode.color = 1;  
  190.                     tempnode.color = 1;  
  191.                     newnode.pNode.pNode.color = 0;  
  192.                     newnode = newnode.pNode.pNode;  
  193.                 } else {  
  194.                     if (newnode == newnode.pNode.rightNode)// 叔父结点为黑并为其父爷点的左子树  
  195.                     {  
  196.                         newnode = newnode.pNode;  
  197.                         leftRotate(newnode, nil);  
  198.                     }  
  199.                     newnode.pNode.color = 1;  
  200.                     newnode.pNode.pNode.color = 0;  
  201.                     rightRotate(newnode.pNode.pNode, nil);  
  202.                 }  
  203.             } else {  
  204.                 tempnode = newnode.pNode.pNode.leftNode;// 叔父结点为爷爷的右子树  
  205.                 if (tempnode.color == 0) {// 叔父结点为红  
  206.                     newnode.pNode.color = 1;  
  207.                     tempnode.color = 1;  
  208.                     newnode.pNode.pNode.color = 0;  
  209.                     newnode = newnode.pNode.pNode;  
  210.                 } else // 叔父结点为黑并为其父爷点的左子树  
  211.                 {  
  212.                     if (newnode == newnode.pNode.leftNode) {  
  213.                         newnode = newnode.pNode;  
  214.                         rightRotate(newnode, nil);  
  215.                     }  
  216.                     newnode.pNode.color = 1;  
  217.                     newnode.pNode.pNode.color = 0;  
  218.   
  219.                     leftRotate(newnode.pNode.pNode, nil);  
  220.                 }  
  221.             }  
  222.         }  
  223.         nil.pNode.color = 1;  
  224.     }  
  225.   
  226.     public static void creatTree(TreeNode nil) {  
  227.         // 新建NIL[T]结点  
  228.         // int number = Integer.parseInt(JOptionPane.showInputDialog("请输入个数:"));  
  229.         int[] number = new int[] { 125781114154 };  
  230.         // int[] number = new int[] { 8,11,17,15,6,1,22,25,27 };  
  231.         for (int i = 0; i < number.length; i++) {  
  232.             // int inputValue = Integer.parseInt(JOptionPane  
  233.             // .showInputDialog("请输入树节点值:"));  
  234.             int inputValue = number[i];  
  235.             InsertTreeNode(inputValue, nil);  
  236.         }  
  237.     }  
  238.   
  239.     public static void deleteTree(TreeNode nil, int i) {  
  240.         /*删除结点主要考虑三个问题: 
  241.          * 1.删除的为叶子节点,即左右子树为空 
  242.          * 2.删除的为带一棵子树的结点 
  243.          * 前面两种情况可以合并讨论,都是直接让父结点指向孩子结点或空节点(左右子树为空时),删除后设置 
  244.          * 旋转结点,进行修复 
  245.          * 3.删除的为有左右子树的结点,需要取得其后继结点,作为新结点 
  246.          *  
  247.           
  248.          *  
  249.          * 
  250.          *  
  251.          *  
  252.          * */  
  253.         // 查找到删除节点,从根结点开始循环遍历  
  254.         TreeNode zNode = new TreeNode(nil, nil, nil, i, 1);  
  255.         TreeNode xNode = new TreeNode(nil, nil, nil, -11);  
  256.         TreeNode tempNode = nil.pNode;// 设置根结点  
  257.         TreeNode rootnode= new TreeNode(nil, nil, nil, -11);  
  258.   
  259.         boolean mark = false;// 查找对象结点  
  260.         while (tempNode != nil && mark == false) {  
  261.             if (zNode.key < tempNode.key) {  
  262.                 tempNode = tempNode.leftNode;  
  263.             } else if (zNode.key > tempNode.key) {  
  264.                 tempNode = tempNode.rightNode;  
  265.             } else {  
  266.                 zNode = tempNode;  
  267.                 mark = true;  
  268.             }  
  269.         }  
  270.         // zNode即为当前节点,进行删除操作  
  271.         TreeNode yNode = new TreeNode(nil, nil, nil, -11);//y结点用于指示被删除节点  
  272.         if ((zNode.leftNode == nil) || (zNode.rightNode == nil)) {  
  273.             yNode = zNode;// 用yNode指向将被删除的结点  
  274.         } else {  
  275.             yNode = lookAfterNode(nil, zNode);// 寻找后继节点  
  276.         }  
  277.         // 进行删除,通过后继与父母结点之间建立双向关系进行删除  
  278.         if (yNode.leftNode != nil) {  
  279.             xNode = yNode.leftNode;  
  280.         } else {  
  281.             xNode = yNode.rightNode;  
  282.         }  
  283.         if ((zNode.leftNode == nil) && (zNode.rightNode == nil)) {  
  284.             rootnode=xNode.pNode;//此时指向空值时,nil的父母节点会改变,所以在此保留根结点,最后恢复时可用  
  285.         }  
  286.         xNode.pNode = yNode.pNode;  
  287.         // //  
  288.   
  289.         if (yNode.pNode == nil) {  
  290.             nil.pNode = xNode;  
  291.         } else if (yNode == yNode.pNode.leftNode) {  
  292.             yNode.pNode.leftNode = xNode;  
  293.         } else {  
  294.             yNode.pNode.rightNode = xNode;  
  295.         }  
  296.         if (yNode != zNode) {  
  297.             zNode.key = yNode.key;  
  298.         }  
  299.         if (yNode.color == 1) {//解决黑黑冲突,如果为红则不需要改变  
  300.             deleteTreeFixUp(nil, xNode);  
  301.         }  
  302.         nil.pNode=rootnode;//还原根结点为nit的父母结点  
  303.     }  
  304.   
  305.     public static TreeNode lookAfterNode(TreeNode nil, TreeNode node) {  
  306.         TreeNode returnNode = new TreeNode(nil, nil, nil, -10);  
  307.         if (node.rightNode != nil) {  
  308.             returnNode = node.rightNode;  
  309.             while (returnNode.leftNode != nil) {  
  310.                 returnNode = returnNode.leftNode;  
  311.             }  
  312.             return returnNode;  
  313.         }  
  314.         returnNode = node.pNode;  
  315.         while (returnNode != nil && node == returnNode.rightNode) {  
  316.             node = returnNode;  
  317.             returnNode = node.pNode;  
  318.         }  
  319.         return returnNode;  
  320.     }  
  321.   
  322.     public static void deleteTreeFixUp(TreeNode nil, TreeNode xNode) {  
  323.         /*  删除修复: 
  324.          *  1.x的兄弟w是红色的 
  325.          *  2.x的兄弟w是黑色的,而且w的两个孩子都是黑色的 
  326.          *  3.x的兄弟w是黑色的,而且w的左孩子为红,右孩子为黑 
  327.          *  4.x的兄弟w是黑色的,而且w的左孩子为黑,右孩子为红 
  328.          *  */  
  329.         TreeNode adjustNode = new TreeNode(nil, nil, nil, -11);  
  330.         while (xNode != nil.pNode && xNode.color == 1) {  
  331.             if (xNode == xNode.pNode.leftNode) {  
  332.                 adjustNode = xNode.pNode.rightNode;  
  333.                 if (adjustNode.color == 0) {  
  334.                     adjustNode.color = 1;  
  335.                     xNode.pNode.color = 0;  
  336.                     leftRotate(xNode.pNode, nil);  
  337.                     adjustNode = xNode.pNode.rightNode;  
  338.                 }  
  339.                 if (adjustNode.leftNode.color == 1  
  340.                         && adjustNode.rightNode.color == 1) {  
  341.                     adjustNode.color = 0;  
  342.                     xNode = xNode.pNode;  
  343.                 } else if (adjustNode.rightNode.color == 1) {  
  344.                     adjustNode.leftNode.color = 1;  
  345.                     adjustNode.color = 0;  
  346.                     rightRotate(adjustNode, nil);  
  347.                     adjustNode = xNode.pNode.rightNode;  
  348.                 }  
  349.                 adjustNode.color = adjustNode.pNode.color;  
  350.                 adjustNode.pNode.color = 1;  
  351.                 adjustNode.rightNode.color = 1;  
  352.                 leftRotate(xNode.pNode, nil);  
  353.                 xNode = nil.pNode;  
  354.             } else {  
  355.                 adjustNode = xNode.pNode.leftNode;  
  356.                 if (adjustNode.color == 0) {  
  357.                     adjustNode.color = 1;  
  358.                     xNode.pNode.color = 0;  
  359.                     rightRotate(xNode.pNode, nil);  
  360.                     adjustNode = xNode.pNode.leftNode;  
  361.                 }  
  362.                 if (adjustNode.rightNode.color == 1  
  363.                         && adjustNode.leftNode.color == 1) {  
  364.                     adjustNode.color = 0;  
  365.                     xNode = xNode.pNode;  
  366.                 } else if (adjustNode.leftNode.color == 1) {  
  367.                     adjustNode.rightNode.color = 1;  
  368.                     adjustNode.color = 0;  
  369.                     leftRotate(adjustNode, nil);  
  370.                     adjustNode = xNode.pNode.leftNode;  
  371.                 }  
  372.                 adjustNode.color = adjustNode.pNode.color;  
  373.                 adjustNode.pNode.color = 1;  
  374.                 adjustNode.leftNode.color = 1;  
  375.                 rightRotate(xNode.pNode, nil);  
  376.                 xNode = nil.pNode;  
  377.             }  
  378.         }  
  379.         xNode.color = 1;  
  380.     }  
  381. }  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值