红黑树-Java版
来源:互联网 发布:硬盘开盘数据恢复 编辑:程序博客网 时间:2024/06/07 04:58
先上代码-注释齐全
package com.uestc.rb;/** * 红黑树的Java实现 younfor@yeah.net * * @author y * */// 定义颜色enum Color { RED, BLACK}// 结点数据结构class Node { private Node left; private Node right; private Node parent; private Color color; private int value; public Node(Node left, Node right, Node parent, Color color, int value) { this.left = left; this.right = right; this.parent = parent; this.color = color; this.value = value; } public Node() { } public Node(int value) { this(null, null, null, null, value); } public Node getLeft() { return left; } public void setLeft(Node left) { this.left = left; } public Node getRight() { return right; } public void setRight(Node right) { this.right = right; } public Node getParent() { return parent; } public void setParent(Node parent) { this.parent = parent; } public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } public int getValue() { return value; } public void setValue(int value) { this.value = value; }}// 红黑树实现类public class RBTree { // 定义空结点 private final Node NIL = new Node(null, null, null, Color.BLACK, -1); // 定义根结点 private Node root = NIL; /** * 插入结点 * * @param node */ public void Insert(Node node) { Node previous = NIL; Node cur = root; // 二叉搜索树寻找插入位置 while (cur != NIL) { previous = cur; if (cur.getValue() < node.getValue()) { cur = cur.getRight(); } else { cur = cur.getLeft(); } } node.setParent(previous); // 设置父子联系-注意空树的情况 if (previous == NIL) { root = node; root.setParent(NIL); } else if (previous.getValue() > node.getValue()) { previous.setLeft(node); } else { previous.setRight(node); } node.setLeft(NIL); node.setRight(NIL); node.setColor(Color.RED); InsertFixup(node); } /** * 插入结点后的调整 * * @param node */ private void InsertFixup(Node node) { // 黑父-pass // 红父 while (node.getParent().getColor() == Color.RED) { // 父亲是左孩子 if (node.getParent() == node.getParent().getParent().getLeft()) { Node rightNuncle = node.getParent().getParent().getRight(); // 红父红叔 if (rightNuncle.getColor() == Color.RED) { rightNuncle.setColor(Color.BLACK); node.getParent().setColor(Color.BLACK); node.getParent().getParent().setColor(Color.RED); node = node.getParent().getParent(); } // 红父黑叔 else { // 如果是右孩子先左旋 if (node == node.getParent().getRight()) { // node = node.getParent(); leftRotate(node); } // 右旋 node.getParent().setColor(Color.BLACK); node.getParent().getParent().setColor(Color.RED); rightRotate(node.getParent().getParent()); } } else { // 父亲是右孩子-镜像 Node leftNuncle = node.getParent().getParent().getLeft(); if (leftNuncle.getColor() == Color.RED) { leftNuncle.setColor(Color.BLACK); node.getParent().setColor(Color.BLACK); node.getParent().getParent().setColor(Color.RED); node = node.getParent().getParent(); } else { if (node == node.getParent().getLeft()) { node = node.getParent(); rightRotate(node); } node.getParent().setColor(Color.BLACK); node.getParent().getParent().setColor(Color.RED); leftRotate(node.getParent().getParent()); } } } root.setColor(Color.BLACK); } /** * 删除结点 * @param data * @return */ public Node Delete(int data) { Node node = search(data); if (node == null) return null; //真正被删除的结点 Node oldNode = NIL; //删除后准备替代的结点 Node newNode = NIL; if (node.getLeft() == NIL || node.getRight() == NIL) { oldNode = node; } else { //当2个儿子的时候用后继(前驱也行) oldNode = previous(node); } //设置替代结点关系 if (oldNode.getLeft() != NIL) { newNode = oldNode.getLeft(); } else { newNode = oldNode.getRight(); } newNode.setParent(oldNode.getParent()); if (oldNode.getParent() == NIL) { root = newNode; } else if (oldNode == oldNode.getParent().getLeft()) { oldNode.getParent().setLeft(newNode); } else { oldNode.getParent().setRight(newNode); } //交换真正删除的结点和替代结点的值(把node的值设置为oldNode的值,相当于真正把oldNode删掉了) if (oldNode != node) { node.setValue(oldNode.getValue()); } //如果旧结点是红色,肯定是叶子结点,直接删了不用调整 //反之从新结点处开始调整 if (oldNode.getColor() == Color.BLACK) { DeleteFixup(newNode); } return oldNode; } // 删除节点后的调整 private void DeleteFixup(Node node) { //首先能走到这里,Old肯定是黑色 //下面讨论新结点情况 // 1.新结点红色直接变为黑色 // 2.新结点为黑色 while (node != root && node.getColor() == Color.BLACK) { if (node == node.getParent().getLeft()) { //新结点在父结点的左孩子 Node rightBrother = node.getParent().getRight(); //2.1 红兄 if (rightBrother.getColor() == Color.RED) { // case 1 // node节点为左孩子,node节点的兄弟为RED rightBrother.setColor(Color.BLACK); node.getParent().setColor(Color.RED); leftRotate(node.getParent()); rightBrother = node.getParent().getRight(); //经过变化转换为黑兄了 } //2.2 黑兄 //2.2.1 黑兄黑侄 if (rightBrother.getLeft().getColor() == Color.BLACK && rightBrother.getRight().getColor() == Color.BLACK) { rightBrother.setColor(Color.RED); node = node.getParent(); //迭代-如果是红父直接会下次跳出,如果不是继续迭代 continue; } else if (rightBrother.getRight().getColor() == Color.BLACK) { //2.2.2 黑兄红侄左 rightBrother.getLeft().setColor(Color.BLACK); rightBrother.setColor(Color.RED); rightRotate(rightBrother); rightBrother = node.getParent().getRight(); //转换为黑兄红侄右 } else { //2.2.3 黑兄红侄右 rightBrother.setColor(node.getParent().getColor()); node.getParent().setColor(Color.BLACK); rightBrother.getRight().setColor(Color.BLACK); leftRotate(node.getParent()); //为了跳出循环 node = root; } } else { Node leftBrother = node.getParent().getLeft(); if (leftBrother.getColor() == Color.RED) { leftBrother.setColor(Color.BLACK); node.getParent().setColor(Color.RED); rightRotate(node.getParent()); leftBrother = node.getParent().getLeft(); } if (leftBrother.getLeft().getColor() == Color.BLACK && leftBrother.getRight().getColor() == Color.BLACK) { leftBrother.setColor(Color.RED); node = node.getParent(); } else if (leftBrother.getLeft().getColor() == Color.BLACK) { leftBrother.setColor(Color.RED); leftBrother.getRight().setColor(Color.BLACK); leftRotate(leftBrother); leftBrother = node.getParent().getLeft(); } else { leftBrother.setColor(node.getParent().getColor()); node.getParent().setColor(Color.BLACK); leftBrother.getLeft().setColor(Color.BLACK); rightRotate(node.getParent()); node = root; } } } node.setColor(Color.BLACK); } /** * 查找前驱结点 * @param node * @return */ public Node previous(Node node) { Node leftChild=node.getLeft(); if(leftChild!=NIL) { Node pre=null; while(leftChild!=NIL) { pre=leftChild; leftChild=leftChild.getRight(); } return pre; }else { Node parent=node.getParent(); while(parent!=NIL&&parent.getRight()!=node) { node=parent; parent=parent.getParent(); } return parent; } } /** * 查找后继结点 * @param node * @return */ public Node successor(Node node) { Node rightChild = node.getRight(); if (rightChild != NIL) { Node previous = null; while (rightChild != NIL) { previous = rightChild; rightChild = rightChild.getLeft(); } return previous; } else { Node parent = node.getParent(); while (parent != NIL && node != parent.getLeft()) { node = parent; parent = parent.getParent(); } return parent; } } /** * 查找结点 * * @param data * @return */ public Node search(int data) { Node temp = root; while (temp != NIL) { if (temp.getValue() == data) { return temp; } else if (data < temp.getValue()) { temp = temp.getLeft(); } else { temp = temp.getRight(); } } return null; } /** * 左旋 * * @param node * 不平衡点 */ private void leftRotate(Node node) { Node rightNode = node.getRight(); // 1 node.setRight(rightNode.getLeft()); rightNode.getLeft().setParent(node); rightNode.setParent(node.getParent()); // 2 if (node.getParent() == NIL) { root = rightNode; } else if (node == node.getParent().getLeft()) { node.getParent().setLeft(rightNode); } else { node.getParent().setRight(rightNode); } // 3 rightNode.setLeft(node); node.setParent(rightNode); } /** * 右旋 * * @param node * 不平衡点 */ private void rightRotate(Node node) { Node leftNode = node.getLeft(); // 1 node.setLeft(leftNode.getRight()); leftNode.getRight().setParent(node); leftNode.setParent(node.getParent()); // 2 if (node.getParent() == NIL) { root = leftNode; } else if (node == node.getParent().getLeft()) { node.getParent().setLeft(leftNode); } else { node.getParent().setRight(leftNode); } // 3 leftNode.setRight(node); node.setParent(leftNode); } /** * 输出 * * @param node */ public void print(Node node) { if (node == NIL) return; print(node.getLeft()); System.out.println(" value:" + node.getValue() + " color:" + node.getColor()); print(node.getRight()); } public Node getRoot() { return root; }}
下面是转载的介绍:
红黑树的平衡
红黑树首先是一棵二叉查找树,它每个结点都被标上了颜色(红色或黑色),红黑树满足以下5个性质:
1、 每个结点的颜色只能是红色或黑色。
2、 根结点是黑色的。
3、 每个叶子结点都带有两个空的黑色结点(被称为黑哨兵),如果一个结点n的只有一个左孩子,那么n的右孩子是一个黑哨兵;如果结点n只有一个右孩子,那么n的左孩子是一个黑哨兵。
4、 如果一个结点是红的,则它的两个儿子都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点。
5、 对于每个结点来说,从该结点到其子孙叶结点的所有路径上包含相同数目的黑结点。
http://blog.csdn.net/very_2/article/details/5722682
0 0
- 红黑树java版
- 红黑树-Java版
- JAVA版GZipUtil.java
- JAVA红黑树
- java红黑树
- 红黑树(Java)
- JAVA红黑树
- java 红黑树
- Java 红黑树
- Java - 《Thinking in Java 第4版》
- Cocos2d-JAVA: Java版的Cocos2d-x
- 数据结构java版三 Java内置数据结构
- Java多线程编程总结 java 1.6版
- Java基础 - 树状数组Java版
- 红黑树之java实现
- java实现红黑树
- 红黑树的Java实现
- 红黑树java实现
- 升级chrome出现SELinux问题的解决方法
- VS配置附加包含目录技巧
- Session数据的持久化读取实现原理
- iOS开发 ----- UIButton
- HDU 3018 Ant Trip(欧拉路径 + 并查集 + 连通性判断)
- 红黑树-Java版
- C库函数使用与总结之时间函数
- C库函数使用与总结之字符串处理函数
- 黑马程序员——Java之集合
- 算法基础之排序
- 字节序问题
- Source Insight常用功能设置
- TCP协议
- ajax缓存问题