概念:每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色,提高二叉树的查找性能;
特性:
性质1. 节点是红色或黑色。
性质2. 根是黑色。
性质3. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
性能:O(log n)的时间之外,每次插入或删除需要O(log n)的空间。
实现:
JAVAQueue:用linkedlist写的队列
- import java.util.LinkedList;
- public class JavaQueue {
- /**
- * @param args
- */
- private LinkedList list = new LinkedList();
- public void push(Object v) {
- list.addFirst(v);
- }
- public Object pop() {
- return list.removeFirst();
- }
- public Object get() {
- return list.removeLast();
- }
- public boolean isEmpty(){
- return list.isEmpty();
- }
- }
JAVAStack:用linkedlist写的堆栈
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.LinkedList;
- import java.util.Map;
- import com.sun.xml.internal.bind.v2.schemagen.xmlschema.List;
- public class JavaStack {
- private LinkedList list = new LinkedList();
- public void push(Object v) {
- list.addFirst(v);
- }
- public Object pop(){
- return list.removeFirst();
- }
- public Object top(){
- return list.getFirst();
- }
- public boolean IsNull(){
- if(list.size()==0) return true;
- else return false;
- }
- /*public static void main(String[] args) {
- // TODO Auto-generated method stub
- JavaStack stack=new JavaStack();
- for(int i=0;i<10;i++)
- {
- stack.push(i);
- }
- System.out.println(stack.top());
- stack.pop();
- System.out.println(stack.top());
- Map map=new HashMap();
- A a=new A();
- A b=new A();
- A c=new A();
- int i=0;
- map.put(i, a);
- map.put(i++, b);
- map.put(i++, c);
- }
- */
- }
TreeNode:定义的节点类
- public class TreeNode {
- //应该包含五个域,left,right,p,key,color;
- TreeNode leftNode;//指示左结点
- TreeNode rightNode;//指示右结点
- TreeNode pNode;//指示父结点或者NIL(T)哨兵结点
- int key;//结点的值
- int color;//其中0表示红,1表示黑
- public TreeNode getLeftNode() {
- return leftNode;
- }
- public void setLeftNode(TreeNode leftNode) {
- this.leftNode = leftNode;
- }
- public TreeNode getRightNode() {
- return rightNode;
- }
- public void setRightNode(TreeNode rightNode) {
- this.rightNode = rightNode;
- }
- public TreeNode getPNode() {
- return pNode;
- }
- public void setPNode(TreeNode node) {
- pNode = node;
- }
- public int getKey() {
- return key;
- }
- public void setKey(int key) {
- this.key = key;
- }
- public int getColor() {
- return color;
- }
- public void setColor(int color) {
- this.color = color;
- }
- //默认构造函数
- public TreeNode(TreeNode leftNode,TreeNode rightNode,TreeNode pNode,int key,int color){
- this.leftNode=leftNode;
- this.rightNode=rightNode;
- this.pNode=pNode;
- this.key=key;
- this.color=color;
- }
- }
TestRBT类:主要功能实现
- import javax.swing.JOptionPane;
- import javax.swing.text.DefaultEditorKit.InsertBreakAction;
- import sun.management.counter.Variability;
- import com.sun.org.apache.regexp.internal.recompile;
- import com.sun.org.apache.xml.internal.security.Init;
- public class TestRBT {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- // 1.建立一棵树,并进行初始化,也可通过插入节点进行建树
- // TreeNode[] node = new TreeNode[23];
- // 插入结点操作
- TreeNode nil = new TreeNode(null, null, null, -1, 1);//设定哨兵节点
- creatTree(nil);// 通过插入结点创建树,并以哨兵节点的父指针指向根节点
- showTree(nil.pNode, nil);// 展示插入建树后的结果
- deleteTree(nil, 8);// 删除节点,删除的节点也可从外部传入
- System.out.println("删除结点后:");
- showTree(nil.pNode, nil);// 展示删除树结点的结果
- }
- public static void initTree(TreeNode node, TreeNode nil) {
- //初始化构造树int[] a={1,2,5,7,8,11,14,15,4}
- TreeNode tempnode = new TreeNode(nil, nil, nil, -1, 1);
- node.leftNode = new TreeNode(nil, nil, node, 2, 0);
- node.rightNode = new TreeNode(nil, nil, node, 14, 1);
- tempnode = node.leftNode;
- tempnode.leftNode = new TreeNode(nil, nil, tempnode, 1, 1);
- tempnode.rightNode = new TreeNode(nil, nil, tempnode, 7, 1);
- tempnode = tempnode.rightNode;
- tempnode.leftNode = new TreeNode(nil, nil, tempnode, 5, 0);
- tempnode.rightNode = new TreeNode(nil, nil, tempnode, 8, 0);
- tempnode = node.rightNode;
- tempnode.rightNode = new TreeNode(nil, nil, tempnode, 15, 0);
- /*
- * int i = 2; while (i < 23) { if ((i == 2) || (i == 3) || (i == 4) ||
- * (i == 6) || (i == 7) || (i == 9) || (i == 11) || (i == 12) || (i ==
- * 14) || (i == 17) || (i == 18) || (i == 19) || (i == 20) || (i == 22))
- * node[i] = new TreeNode(nil, nil, nil, i, 1); i++; } // 赋值
- * node[7].setLeftNode(node[4]); node[7].setRightNode(node[11]);
- * node[4].setLeftNode(node[3]); node[4].setRightNode(node[6]);
- * node[4].setPNode(node[7]); node[3].setLeftNode(node[2]);
- * node[3].setPNode(node[4]); node[2].setPNode(node[3]);
- * node[6].setPNode(node[4]);
- *
- * node[11].setLeftNode(node[9]); node[11].setRightNode(node[18]);
- * node[11].setPNode(node[7]);
- *
- * node[18].setLeftNode(node[14]); node[18].setRightNode(node[19]);
- * node[18].setPNode(node[11]);
- *
- * node[14].setLeftNode(node[12]); node[14].setRightNode(node[17]);
- * node[14].setPNode(node[18]);
- *
- * node[19].setRightNode(node[22]); node[19].setPNode(node[18]);
- *
- * node[22].setLeftNode(node[20]); node[22].setPNode(node[19]);
- *
- * node[12].setPNode(node[14]); node[17].setPNode(node[14]);
- * node[20].setPNode(node[22]); // show(node);
- *
- */
- }
- public static void showTree(TreeNode node, TreeNode nil) {
- // 中序循环遍历树
- /*
- * JavaStack stack = new JavaStack(); // 将根结点输入栈中 while (node != nil ||
- * !stack.IsNull()) { if (node != nil) { stack.push(node); node =
- * node.leftNode; } else { TreeNode tempnode = (TreeNode) stack.pop();
- * System.out.print(tempnode.key+" " ); if (tempnode.rightNode != nil)
- * node = tempnode.rightNode; } }
- */
- // 层次遍历,分别打印出树的根结点,不用递归用循环提高效率
- JavaQueue queue = new JavaQueue();
- queue.push(node);// 将根结点输入栈中
- while (!queue.isEmpty()) {//队列不为空则出队列,继续添加新节点
- /**/
- TreeNode tempnode = (TreeNode) queue.get();
- int key = tempnode.key;
- StringBuffer str = new StringBuffer();//通过StringBuffer进行输出
- str.append("key:" + key);
- if (tempnode.color == 0) {
- str.append(" color:红色");
- } else {
- str.append(" color:黑色");
- }
- if (tempnode.leftNode != nil && tempnode.leftNode != null) {
- str.append(" lefttree:" + tempnode.leftNode.key);
- queue.push(tempnode.leftNode);
- }
- if (tempnode.rightNode != nil) {
- str.append(" righttree:" + tempnode.rightNode.key);
- queue.push(tempnode.rightNode);
- }
- System.out.println(str.toString());
- }
- }
- public static void leftRotate(TreeNode xnode, TreeNode nil) {
- //左旋转的实际为改变节点的前趋后继,三个节点,当前节点,当前节点的右节点,当前节点右节点的左节点
- TreeNode yNode = xnode.rightNode;// 设置右孩子为y结点
- xnode.rightNode = yNode.leftNode;
- if (yNode.leftNode != nil)
- yNode.leftNode.pNode = xnode;
- yNode.pNode = xnode.pNode;
- if (xnode.pNode == nil) {
- nil.pNode = yNode;
- } else if (xnode == xnode.pNode.leftNode) {
- xnode.pNode.leftNode = yNode;
- } else {
- xnode.pNode.rightNode = yNode;
- }
- yNode.leftNode = xnode;
- xnode.pNode = yNode;
- }
- public static void rightRotate(TreeNode xnode, TreeNode nil) {
- TreeNode yNode = xnode.leftNode;// 设置左孩子为y结点
- xnode.leftNode = yNode.rightNode;
- if (yNode.rightNode != nil) {
- yNode.rightNode.pNode = xnode;
- }
- yNode.pNode = xnode.pNode;
- if (xnode.pNode == nil) {
- nil.pNode = yNode;
- } else if (xnode == xnode.pNode.rightNode) {
- xnode.pNode.rightNode = yNode;
- } else {
- xnode.pNode.leftNode = yNode;
- }
- yNode.rightNode = xnode;
- xnode.pNode = yNode;
- }
- public static void InsertTreeNode(int i, TreeNode nil) {
- TreeNode newnode = new TreeNode(nil, nil, nil, i, 0);// 设置新插入结点初始值为i
- TreeNode tempnode = new TreeNode(nil, nil, nil, -1, 0);// 设置比较结点的父结点
- TreeNode recnode = new TreeNode(nil, nil, nil, -1, 0);// 设置一个循环树结点
- // 执行查找过程,找到相应的位置并进行插入,随后进行红黑性质的插入调整
- recnode = nil.pNode;
- if (recnode == null) {
- nil.pNode = newnode;
- newnode.color = 1;
- } else {
- while (recnode != nil) {
- tempnode = recnode;
- if (i < recnode.key) {
- recnode = recnode.leftNode;
- } else {
- recnode = recnode.rightNode;
- }
- }
- newnode.pNode = tempnode;
- if (newnode.key < tempnode.key) {
- tempnode.leftNode = newnode;
- } else {
- tempnode.rightNode = newnode;
- }
- // 执行修补程序
- InsertTreeNodeFixup(nil, newnode);
- }
- }
- public static void InsertTreeNodeFixup(TreeNode nil, TreeNode newnode) {
- TreeNode tempnode = new TreeNode(nil, nil, nil, -1, 0);
- /*执行插入主要解决红红冲突,具体情况有三种,注意插入的结点默认均为红色
- * 1.newnode 的叔叔为红,即将其父,叔结点均置为黑
- * 2.newnode 的叔叔是黑,newnode为父结点的右孩子
- * 3.newnode 的叔叔是黑,newnode为父结点的左孩子
- * 2,3的解决办法是先进行一次相应方向的旋转(左子树即左转,右子树即右转),然后将newnode设为祖父结点,
- * 进行相应的反方向转动,最后设置根结点值为黑色
- * 插入操作可通过两次旋转彻底解决平衡问题
- */
- while (newnode.pNode.color == 0) {
- if (newnode.pNode == newnode.pNode.pNode.leftNode) {
- tempnode = newnode.pNode.pNode.rightNode;// 叔父结点为爷爷的左子树
- if (tempnode.color == 0) {// 叔父结点为红
- newnode.pNode.color = 1;
- tempnode.color = 1;
- newnode.pNode.pNode.color = 0;
- newnode = newnode.pNode.pNode;
- } else {
- if (newnode == newnode.pNode.rightNode)// 叔父结点为黑并为其父爷点的左子树
- {
- newnode = newnode.pNode;
- leftRotate(newnode, nil);
- }
- newnode.pNode.color = 1;
- newnode.pNode.pNode.color = 0;
- rightRotate(newnode.pNode.pNode, nil);
- }
- } else {
- tempnode = newnode.pNode.pNode.leftNode;// 叔父结点为爷爷的右子树
- if (tempnode.color == 0) {// 叔父结点为红
- newnode.pNode.color = 1;
- tempnode.color = 1;
- newnode.pNode.pNode.color = 0;
- newnode = newnode.pNode.pNode;
- } else // 叔父结点为黑并为其父爷点的左子树
- {
- if (newnode == newnode.pNode.leftNode) {
- newnode = newnode.pNode;
- rightRotate(newnode, nil);
- }
- newnode.pNode.color = 1;
- newnode.pNode.pNode.color = 0;
- leftRotate(newnode.pNode.pNode, nil);
- }
- }
- }
- nil.pNode.color = 1;
- }
- public static void creatTree(TreeNode nil) {
- // 新建NIL[T]结点
- // int number = Integer.parseInt(JOptionPane.showInputDialog("请输入个数:"));
- int[] number = new int[] { 1, 2, 5, 7, 8, 11, 14, 15, 4 };
- // int[] number = new int[] { 8,11,17,15,6,1,22,25,27 };
- for (int i = 0; i < number.length; i++) {
- // int inputValue = Integer.parseInt(JOptionPane
- // .showInputDialog("请输入树节点值:"));
- int inputValue = number[i];
- InsertTreeNode(inputValue, nil);
- }
- }
- public static void deleteTree(TreeNode nil, int i) {
- /*删除结点主要考虑三个问题:
- * 1.删除的为叶子节点,即左右子树为空
- * 2.删除的为带一棵子树的结点
- * 前面两种情况可以合并讨论,都是直接让父结点指向孩子结点或空节点(左右子树为空时),删除后设置
- * 旋转结点,进行修复
- * 3.删除的为有左右子树的结点,需要取得其后继结点,作为新结点
- *
- *
- *
- *
- *
- * */
- // 查找到删除节点,从根结点开始循环遍历
- TreeNode zNode = new TreeNode(nil, nil, nil, i, 1);
- TreeNode xNode = new TreeNode(nil, nil, nil, -1, 1);
- TreeNode tempNode = nil.pNode;// 设置根结点
- TreeNode rootnode= new TreeNode(nil, nil, nil, -1, 1);
- boolean mark = false;// 查找对象结点
- while (tempNode != nil && mark == false) {
- if (zNode.key < tempNode.key) {
- tempNode = tempNode.leftNode;
- } else if (zNode.key > tempNode.key) {
- tempNode = tempNode.rightNode;
- } else {
- zNode = tempNode;
- mark = true;
- }
- }
- // zNode即为当前节点,进行删除操作
- TreeNode yNode = new TreeNode(nil, nil, nil, -1, 1);//y结点用于指示被删除节点
- if ((zNode.leftNode == nil) || (zNode.rightNode == nil)) {
- yNode = zNode;// 用yNode指向将被删除的结点
- } else {
- yNode = lookAfterNode(nil, zNode);// 寻找后继节点
- }
- // 进行删除,通过后继与父母结点之间建立双向关系进行删除
- if (yNode.leftNode != nil) {
- xNode = yNode.leftNode;
- } else {
- xNode = yNode.rightNode;
- }
- if ((zNode.leftNode == nil) && (zNode.rightNode == nil)) {
- rootnode=xNode.pNode;//此时指向空值时,nil的父母节点会改变,所以在此保留根结点,最后恢复时可用
- }
- xNode.pNode = yNode.pNode;
- // //
- if (yNode.pNode == nil) {
- nil.pNode = xNode;
- } else if (yNode == yNode.pNode.leftNode) {
- yNode.pNode.leftNode = xNode;
- } else {
- yNode.pNode.rightNode = xNode;
- }
- if (yNode != zNode) {
- zNode.key = yNode.key;
- }
- if (yNode.color == 1) {//解决黑黑冲突,如果为红则不需要改变
- deleteTreeFixUp(nil, xNode);
- }
- nil.pNode=rootnode;//还原根结点为nit的父母结点
- }
- public static TreeNode lookAfterNode(TreeNode nil, TreeNode node) {
- TreeNode returnNode = new TreeNode(nil, nil, nil, -1, 0);
- if (node.rightNode != nil) {
- returnNode = node.rightNode;
- while (returnNode.leftNode != nil) {
- returnNode = returnNode.leftNode;
- }
- return returnNode;
- }
- returnNode = node.pNode;
- while (returnNode != nil && node == returnNode.rightNode) {
- node = returnNode;
- returnNode = node.pNode;
- }
- return returnNode;
- }
- public static void deleteTreeFixUp(TreeNode nil, TreeNode xNode) {
- /* 删除修复:
- * 1.x的兄弟w是红色的
- * 2.x的兄弟w是黑色的,而且w的两个孩子都是黑色的
- * 3.x的兄弟w是黑色的,而且w的左孩子为红,右孩子为黑
- * 4.x的兄弟w是黑色的,而且w的左孩子为黑,右孩子为红
- * */
- TreeNode adjustNode = new TreeNode(nil, nil, nil, -1, 1);
- while (xNode != nil.pNode && xNode.color == 1) {
- if (xNode == xNode.pNode.leftNode) {
- adjustNode = xNode.pNode.rightNode;
- if (adjustNode.color == 0) {
- adjustNode.color = 1;
- xNode.pNode.color = 0;
- leftRotate(xNode.pNode, nil);
- adjustNode = xNode.pNode.rightNode;
- }
- if (adjustNode.leftNode.color == 1
- && adjustNode.rightNode.color == 1) {
- adjustNode.color = 0;
- xNode = xNode.pNode;
- } else if (adjustNode.rightNode.color == 1) {
- adjustNode.leftNode.color = 1;
- adjustNode.color = 0;
- rightRotate(adjustNode, nil);
- adjustNode = xNode.pNode.rightNode;
- }
- adjustNode.color = adjustNode.pNode.color;
- adjustNode.pNode.color = 1;
- adjustNode.rightNode.color = 1;
- leftRotate(xNode.pNode, nil);
- xNode = nil.pNode;
- } else {
- adjustNode = xNode.pNode.leftNode;
- if (adjustNode.color == 0) {
- adjustNode.color = 1;
- xNode.pNode.color = 0;
- rightRotate(xNode.pNode, nil);
- adjustNode = xNode.pNode.leftNode;
- }
- if (adjustNode.rightNode.color == 1
- && adjustNode.leftNode.color == 1) {
- adjustNode.color = 0;
- xNode = xNode.pNode;
- } else if (adjustNode.leftNode.color == 1) {
- adjustNode.rightNode.color = 1;
- adjustNode.color = 0;
- leftRotate(adjustNode, nil);
- adjustNode = xNode.pNode.leftNode;
- }
- adjustNode.color = adjustNode.pNode.color;
- adjustNode.pNode.color = 1;
- adjustNode.leftNode.color = 1;
- rightRotate(xNode.pNode, nil);
- xNode = nil.pNode;
- }
- }
- xNode.color = 1;
- }
- }