红黑树黑高度的验证方法
public void depthFirst(){
depthFirst(root,0);//包装方法
}
private void depthFirst(BinaryNode node,int count){//count用于保存黑高度
if (node==null) {
System.out.println(count);return;}//如果到达了空节点打印出黑高度
else {
if(node.color==BLACK){
depthFirst(node.leftChild,count+1);//如果节点是黑色 黑高度计数器增加
depthFirst(node.rightChild,count+1);//如果节点是黑色 黑高度计数器增加
}
else {
depthFirst(node.leftChild,count); //不是黑色 步增加计数
depthFirst(node.rightChild,count);
}
}
}
test类进行随机添加、删除检验
如果打印出的黑高度相同 证明RedBlackTree类保持了红黑树的性质
/**
* Created by root on 16-3-16.
*/
import java.util.Random;
public class Test {
public static void main(String[] args){
RedBlackTree tree =new RedBlackTree();
Random random=new Random();
//随机法检验
int k=200;
Integer [] a=new Integer[k];
for(int i=0;i<k;i++){
a[i]=random.nextInt(100)+1;
}
for(Integer x :a){
tree.insert(x);
}
for(int i=0;i<150;i++){
tree.remove(random.nextInt(100)+1);}
tree.depthFirst();
}
}
BinaryNode类
/**
* Created by root on 16-3-16.
*/
public class BinaryNode<E extends Comparable> {
public static boolean RED =true; //用布尔型变量存放颜色值
public static boolean BLACK= false;
BinaryNode parent;
BinaryNode leftChild;
BinaryNode rightChild;
E item;
boolean color;
public BinaryNode(E item){ //默认红色 parent leftChild rightChild 默认都是null
this(item,RED);
}
public BinaryNode(E item,boolean color){
this(item,color,null,null,null);
}
public BinaryNode(E item,boolean color,BinaryNode parent,BinaryNode leftChild,BinaryNode rightChild){ //构造器
this.item=item;
this.color=color;
this.parent=parent;
this.leftChild=leftChild;
this.rightChild=rightChild;
}
}
RedBlackTree类中避免空指针的方法
public static boolean BLACK = false;
public static boolean RED = true;
BinaryNode root;
private void setParent(BinaryNode child,BinaryNode parent){ //setParent方法 避免空指针异常
if(child!=null){
child.parent=parent;
}
}
private boolean setColor(BinaryNode node, boolean color) { //设置颜色 避免空指针异常
if (node != null) {
node.color = color;
return true;
}
return false;
}
private void setLeftChild(BinaryNode child, BinaryNode parent) {//为parent设置左子树 避免空指针异常
if (parent != null) {
parent.leftChild = child;
}
if (child != null) {
child.parent = parent;
}
}
private void setRightChild(BinaryNode child, BinaryNode parent) {//同上
if (parent != null) {
parent.rightChild = child;
}
if (child != null) {
child.parent = parent;
}
}
private boolean isBLACKOrNull(BinaryNode node) {//判断节点是空节点或者是黑色节点
return node == null || node.color == BLACK;
}
private boolean isRoot(BinaryNode node) { //节点是root节点?
return node != null && node.parent == null;
}
private boolean isLeftChildOf(BinaryNode child, BinaryNode parent) {//是否是右child
return parent != null && parent.leftChild == child;
}
private boolean isRightChildOf(BinaryNode child, BinaryNode parent) {//是否是左child
return parent != null && parent.rightChild == child;
}
private boolean hasTwoChildren(BinaryNode node) {//是否有两个child
return node != null && node.leftChild != null && node.rightChild != null;
}
private boolean hasOnlyLeftChild(BinaryNode node) {//只有左child
return node != null && node.leftChild != null && node.rightChild == null;
}
private boolean hasOnlyRightChild(BinaryNode node) {//只有右child
return node != null && node.leftChild == null && node.rightChild != null;
}
private boolean isLeaf(BinaryNode node) {//是否是树叶?
return node != null && node.leftChild == null && node.rightChild == null;
}
左旋
private void leftRotate(BinaryNode x) {
BinaryNode y = x.rightChild;
setRightChild(y.leftChild, x);
if (isRoot(x)) {
this.root = y;
y.parent = x.parent;
} else {
if (isLeftChildOf(x, x.parent)) {
setLeftChild(y, x.parent);
} else {
setRightChild(y, x.parent);
}
}
setLeftChild(x, y);
}
右旋
private void rightRotate(BinaryNode y) {
BinaryNode x = y.leftChild;
setLeftChild(x.rightChild, y);
if (isRoot(y)) {
this.root = x;
x.parent = y.parent;
} else {
if (isLeftChildOf(y, y.parent)) {
setLeftChild(x, y.parent);
} else {
setRightChild(x, y.parent);
}
}
setRightChild(y, x);
}
增加节点后的修复:新节点是红色的
如果新节点的parent是黑色的 不需要修复
BinaryNode uncle = grandparent.rightChild;
if (uncle != null && uncle.color == RED) {
setColor(uncle, BLACK);
setColor(parent, BLACK);
setColor(grandparent, RED);
node = grandparent;
continue;
leftRotate(parent);
BinaryNode tmp = node;
node = parent;
parent = node;
setColor(parent, BLACK);
setColor(grandparent, RED);
rightRotate(grandparent);
删除的操作
private void remove(BinaryNode node) {
boolean removeColor;
BinaryNode x;
BinaryNode pOfx;
if (hasTwoChildren(node)) {
BinaryNode inOrderSuccessor =node.rightChild;
while (inOrderSuccessor.leftChild!=null){
inOrderSuccessor=inOrderSuccessor.leftChild;
}
removeColor=inOrderSuccessor.color;
x=inOrderSuccessor.rightChild;
if(isRightChildOf(inOrderSuccessor,node)){
setLeftChild(node.leftChild,inOrderSuccessor);
pOfx=inOrderSuccessor;
}
else {
pOfx=inOrderSuccessor.parent;
setLeftChild(inOrderSuccessor.rightChild,inOrderSuccessor.parent);
setLeftChild(node.leftChild,inOrderSuccessor);
setRightChild(node.rightChild,inOrderSuccessor);
}
if(isRoot(node)){
this.root=inOrderSuccessor;
inOrderSuccessor.parent=node.parent;
}
else {
if(isLeftChildOf(node,node.parent)){
setLeftChild(inOrderSuccessor,node.parent);
}
else {
setRightChild(inOrderSuccessor,node.parent);
}
}
setColor(inOrderSuccessor,node.color);
if(removeColor==BLACK){
removeFix(x,pOfx);
}
} else {
BinaryNode child;
if (hasOnlyLeftChild(node)) {
child = node.leftChild;
} else if (hasOnlyRightChild(node)) {
child = node.rightChild;
} else {
child = null;
}
x = child;
removeColor = node.color;
pOfx = node.parent;
if (isLeftChildOf(node, node.parent)) {
setLeftChild(child, node.parent);
} else if (isRoot(node)) {
this.root = child;
setParent(child,node.parent);
} else {
setRightChild(child, node.parent);
}
if (removeColor == BLACK) {
removeFix(x, pOfx);
}
}
this.root.color=BLACK;
}
删除后的修复
如果被删除的节点有两个children x就是在执行删除之前 node的中序后继的右子树 pOfx是执行删除操作之后x的parent
如果被删除的节点只有一个child或者没有child 那么 x就是node的唯一child或者 是null pOfx是node的parent
最后给出RedBlackTree类
/**
* Created by root on 16-3-16.
*/
public class RedBlackTree<E extends Comparable> {
public static boolean BLACK = false;
public static boolean RED = true;
BinaryNode root;
private void setParent(BinaryNode child,BinaryNode parent){
if(child!=null){
child.parent=parent;
}
}
private boolean setColor(BinaryNode node, boolean color) {
if (node != null) {
node.color = color;
return true;
}
return false;
}
private void setLeftChild(BinaryNode child, BinaryNode parent) {
if (parent != null) {
parent.leftChild = child;
}
if (child != null) {
child.parent = parent;
}
}
private void setRightChild(BinaryNode child, BinaryNode parent) {
if (parent != null) {
parent.rightChild = child;
}
if (child != null) {
child.parent = parent;
}
}
private boolean isBLACKOrNull(BinaryNode node) {
return node == null || node.color == BLACK;
}
private boolean isRoot(BinaryNode node) {
return node != null && node.parent == null;
}
private boolean isLeftChildOf(BinaryNode child, BinaryNode parent) {
return parent != null && parent.leftChild == child;
}
private boolean isRightChildOf(BinaryNode child, BinaryNode parent) {
return parent != null && parent.rightChild == child;
}
private boolean hasTwoChildren(BinaryNode node) {
return node != null && node.leftChild != null && node.rightChild != null;
}
private boolean hasOnlyLeftChild(BinaryNode node) {
return node != null && node.leftChild != null && node.rightChild == null;
}
private boolean hasOnlyRightChild(BinaryNode node) {
return node != null && node.leftChild == null && node.rightChild != null;
}
private boolean isLeaf(BinaryNode node) {
return node != null && node.leftChild == null && node.rightChild == null;
}
private void leftRotate(BinaryNode x) {
BinaryNode y = x.rightChild;
setRightChild(y.leftChild, x);
if (isRoot(x)) {
this.root = y;
y.parent = x.parent;
} else {
if (isLeftChildOf(x, x.parent)) {
setLeftChild(y, x.parent);
} else {
setRightChild(y, x.parent);
}
}
setLeftChild(x, y);
}
private void rightRotate(BinaryNode y) {
BinaryNode x = y.leftChild;
setLeftChild(x.rightChild, y);
if (isRoot(y)) {
this.root = x;
x.parent = y.parent;
} else {
if (isLeftChildOf(y, y.parent)) {
setLeftChild(x, y.parent);
} else {
setRightChild(x, y.parent);
}
}
setRightChild(y, x);
}
private void insertFix(BinaryNode node) {
BinaryNode parent;
while ((parent = node.parent) != null && parent.color == RED) {
BinaryNode grandparent = parent.parent;
if (isLeftChildOf(parent, grandparent)) {
BinaryNode uncle = grandparent.rightChild;
if (uncle != null && uncle.color == RED) {
setColor(uncle, BLACK);
setColor(parent, BLACK);
setColor(grandparent, RED);
node = grandparent;
continue;
} else if (isRightChildOf(node, parent)) {
leftRotate(parent);
BinaryNode tmp = node;
node = parent;
parent = node;
} else {
setColor(parent, BLACK);
setColor(grandparent, RED);
rightRotate(grandparent);
}
} else {
BinaryNode uncle = grandparent.leftChild;
if (uncle != null && uncle.color == RED) {
setColor(uncle, BLACK);
setColor(parent, BLACK);
setColor(grandparent, RED);
node = grandparent;
continue;
} else if (isLeftChildOf(node, parent)) {
rightRotate(parent);
BinaryNode tmp = node;
node = parent;
parent = tmp;
} else {
setColor(parent, BLACK);
setColor(grandparent, RED);
leftRotate(grandparent);
}
}
}
setColor(root, BLACK);
}
public void insert(E item) {
BinaryNode newNode = new BinaryNode(item);
if (this.root == null) {
this.root = newNode;
setColor(root, BLACK);
return;
}
BinaryNode prev = root;
BinaryNode next = root;
while (next != null) {
prev = next;
int comparison = item.compareTo(prev.item);
if (comparison == 0) {
return;
} else if (comparison < 0) {
next = prev.leftChild;
} else {
next = prev.rightChild;
}
}
int comparison = item.compareTo(prev.item);
if (comparison < 0) {
setLeftChild(newNode, prev);
} else {
setRightChild(newNode, prev);
}
insertFix(newNode);
}
public void remove(E item){
BinaryNode node=root;
while(node!=null){
int comparison=item.compareTo(node.item);
if(comparison==0){
remove(node);
return;
}
else if(comparison<0){
node=node.leftChild;
}
else {
node=node.rightChild;
}
}
}
private void remove(BinaryNode node) {
boolean removeColor;
BinaryNode x;
BinaryNode pOfx;
if (hasTwoChildren(node)) {
BinaryNode inOrderSuccessor =node.rightChild;
while (inOrderSuccessor.leftChild!=null){
inOrderSuccessor=inOrderSuccessor.leftChild;
}
removeColor=inOrderSuccessor.color;
x=inOrderSuccessor.rightChild;
if(isRightChildOf(inOrderSuccessor,node)){
setLeftChild(node.leftChild,inOrderSuccessor);
pOfx=inOrderSuccessor;
}
else {
pOfx=inOrderSuccessor.parent;
setLeftChild(inOrderSuccessor.rightChild,inOrderSuccessor.parent);
setLeftChild(node.leftChild,inOrderSuccessor);
setRightChild(node.rightChild,inOrderSuccessor);
}
if(isRoot(node)){
this.root=inOrderSuccessor;
inOrderSuccessor.parent=node.parent;
}
else {
if(isLeftChildOf(node,node.parent)){
setLeftChild(inOrderSuccessor,node.parent);
}
else {
setRightChild(inOrderSuccessor,node.parent);
}
}
setColor(inOrderSuccessor,node.color);
if(removeColor==BLACK){
removeFix(x,pOfx);
}
} else {
BinaryNode child;
if (hasOnlyLeftChild(node)) {
child = node.leftChild;
} else if (hasOnlyRightChild(node)) {
child = node.rightChild;
} else {
child = null;
}
x = child;
removeColor = node.color;
pOfx = node.parent;
if (isLeftChildOf(node, node.parent)) {
setLeftChild(child, node.parent);
} else if (isRoot(node)) {
this.root = child;
setParent(child,node.parent);
} else {
setRightChild(child, node.parent);
}
if (removeColor == BLACK) {
removeFix(x, pOfx);
}
}
this.root.color=BLACK;
}
private void removeFix(BinaryNode x, BinaryNode pOfx) {
while (isBLACKOrNull(x) && pOfx != null) {
if (isLeftChildOf(x, pOfx)) {
BinaryNode w = pOfx.rightChild;
if (w != null && w.color == RED) {
setColor(w, BLACK);
setColor(pOfx, RED);
leftRotate(pOfx);
w = pOfx.rightChild;
} else if (isBLACKOrNull(w.leftChild) && isBLACKOrNull(w.rightChild)) {
setColor(w, RED);
x = pOfx;
pOfx = x.parent;
} else {
if (w.rightChild!=null && w.rightChild.color==RED) {
setColor(w,w.parent.color);
setColor(w.parent,BLACK);
setColor(w.rightChild,BLACK);
leftRotate(pOfx);
x=this.root; //退出循环 并且把root设置为黑色
break;
} else { //w.leftChild.color== RED && w.rightChild.color != RED
setColor(w.leftChild,BLACK);
setColor(w,RED);
rightRotate(w);
w=pOfx.rightChild;
}
}
} else {
BinaryNode w = pOfx.leftChild;
if (w != null && w.color == RED) {
setColor(w, BLACK);
setColor(pOfx, RED);
rightRotate(pOfx);
w = pOfx.leftChild;
} else if (isBLACKOrNull(w.leftChild) && isBLACKOrNull(w.rightChild)) {
setColor(w, RED);
x = pOfx;
pOfx = x.parent;
}
else {
if(w.leftChild!=null && w.leftChild.color==RED){
setColor(w,pOfx.color);
setColor(pOfx,BLACK);
setColor(w.leftChild,BLACK);
rightRotate(pOfx);
x=this.root;
break;
}
else {
setColor(w.rightChild,BLACK);
setColor(w,RED);
leftRotate(w);
w=pOfx.leftChild;
}
}
}
}
setColor(x,BLACK);
}
public static class Queue {
linkedNode beginMaker;
linkedNode endMaker;
public boolean isEmpty() {
return size == 0;
}
private int size;
public Queue() {
beginMaker = new linkedNode(null, null, null);
endMaker = new linkedNode(null, beginMaker, null);
beginMaker.next = endMaker;
this.size = 0;
}
public void add(BinaryNode el) {
linkedNode prevOfEndMaker = endMaker.prev;
linkedNode newNode = new linkedNode(el, prevOfEndMaker, endMaker);
prevOfEndMaker.next = newNode;
endMaker.prev = newNode;
this.size++;
}
public BinaryNode remove() {
if (size != 0) {
linkedNode top = beginMaker.next;
BinaryNode el = top.el;
linkedNode nextOfTop = top.next;
beginMaker.next = nextOfTop;
nextOfTop.prev = beginMaker;
size--;
return el;
}
return null;
}
}
public static class linkedNode {
linkedNode prev;
linkedNode next;
BinaryNode el;
public linkedNode(BinaryNode el) {
this(el, null, null);
}
public linkedNode() {
this(null, null, null);
}
public linkedNode(BinaryNode el, linkedNode prev, linkedNode next) {
this.el = el;
this.prev = prev;
this.next = next;
}
}
public void breadthFirstPrint() {
Queue q = new Queue();
BinaryNode node = root;
q.add(node);
while (!q.isEmpty()) {
node = q.remove();
System.out.println(node.item.toString()+node.color);
if (node.leftChild != null) {
q.add(node.leftChild);
}
if (node.rightChild != null) {
q.add(node.rightChild);
}
}
}
public void inOrderPrint() {
inOrderPrint(this.root);
}
public void inOrderPrint(BinaryNode node) {
if (node == null) return;
inOrderPrint(node.leftChild);
System.out.println(node.item);
inOrderPrint(node.rightChild);
}
public void depthFirst(){
depthFirst(root,0);
}
private void depthFirst(BinaryNode node,int count){
if (node==null) {
System.out.println(count);return;}
else {
if(node.color==BLACK){
depthFirst(node.leftChild,count+1);
depthFirst(node.rightChild,count+1);
}
else {
depthFirst(node.leftChild,count);
depthFirst(node.rightChild,count);
}
}
}
}