红黑树及其操作-java
效果图:
(b)代表黑色
(r)代表红色
二叉树核心代码:Tree.java
package 自平衡二叉搜索树.core;
import java.util.LinkedList;
import 自平衡二叉搜索树.test.PrintfTree;
public class Tree<T,E> {
public Node<T,E> root;//根节点
public Integer size=0;
/**
* 左旋
* p为旋转的中心点
*/
public void rotateLeft(Node<T,E> p) {
if (p != null) {
Node<T,E> r = p.right;
p.right = r.left;
if (r.left != null)
r.left.parent = p;
r.parent = p.parent;
if (p.parent == null)
root = r;
else if (p.parent.left == p)
p.parent.left = r;
else
p.parent.right = r;
r.left = p;
p.parent = r;
}
}
/**
* 右旋
*/
public void rotateRight(Node<T,E> p) {
if (p != null) {
Node<T,E> l = p.left;
p.left = l.right;
if (l.right != null) l.right.parent = p;
l.parent = p.parent;
if (p.parent == null)
root = l;
else if (p.parent.right == p)
p.parent.right = l;
else p.parent.left = l;
l.right = p;
p.parent = l;
}
}
/***
* 先序遍历
* @param p
*/
public void preDis(Node<T,E> p) {
if(p==null)
return;
if(p==root) {
System.out.println(p.e+" (b) 是根节点");
}else {
if(p==p.parent.left) {
System.out.println(p.e+" ("+p.color+")\t 是 "+p.parent.e+" 的 left 孩子");
}else {
System.out.println(p.e+" ("+p.color+")\t 是 "+p.parent.e+" 的 right 孩子");
}
}
preDis(p.left);
preDis(p.right);
}
/***
* 先序遍历
* @param p
*/
public void preDis2(Node<T,E> p) {
if(p==null)
return;
System.out.println(p.e);
preDis(p.left);
preDis(p.right);
}
/***
* 中序遍历
* @param p
*/
public void cenDis(Node<T,E> p) {
if(p==null)
return;
cenDis(p.left);
System.out.println(p.e+" "+p.color);
cenDis(p.right);
}
/**
* 层级遍历
*/
public void cengDis(Node<T,E> p) {
LinkedList<Node<T,E>> stack=new LinkedList<>();
LinkedList<Node<T,E>> dui=new LinkedList<>();
PrintfTree tree = null;
dui.add(p);
while(true){
Node<T,E> f=null;
if(dui.size()>0) {
f=dui.removeFirst();
}
if(f==null) {
Node<T,E> d=null;
if(stack.size()>0) {
d=stack.removeFirst();
}
if(d==null) {
tree.show();
return ;
}else {
dui.addLast(d);
while(true) {
d=null;
if(stack.size()>0) {
d=stack.removeFirst();
}
if(d==null) {
break;
}else {
dui.addLast(d);
}
}
}
}else {
if(tree==null) {
tree=new PrintfTree(""+f.e+"("+f.color+")");
}else {
tree.add(new PrintfTree(""+f.e+"("+f.color+")"));
}
Node<T,E> left=f.left;
if(left!=null) {
stack.addLast(left);
}
Node<T,E> right=f.right;
if(right!=null) {
stack.addLast(right);
}
}
}
}
/***
* 得到节点
* @param key
* @return
*/
public E getE(Integer key) {
if (key == null)//不允许key值为null
throw new NullPointerException();
Node<T,E> p = root;
while (p != null) {
int cmp = p.key;
if (cmp > key)//向左找
p = p.left;
else if (cmp < key)//向右找
p = p.right;
else
return p.e;
}
return null;
}
/**
* 寻找待删节点的后继节点
* @param t
* @return
*/
public Node<T,E> successor(Node<T,E> t) {
if (t == null)
return null;
else if (t.right != null) {
Node<T,E> p = t.right;
while (p.left != null)
p = p.left;
return p;
} else {
Node<T,E> p = t.parent;
Node<T,E> ch = t;
while (p != null && ch == p.right) {
ch = p;
p = p.parent;
}
return p;
}
}
public E put(Integer key,E e) {
int cmp;
Node<T,E> parent;
Node<T,E> t=root;
if (key == null)
throw new NullPointerException();
do {
parent = t;
cmp = t.key;
if (cmp > key) t = t.left;//向左找
else if (cmp < key) t = t.right;//向右找
else return t.setValue(e);
} while (t != null);
Node<T,E> ve = new Node<T,E>(key, e,"r", parent);//创建并插入新的entry
if (cmp > key) parent.left = ve;
else parent.right = ve;
fixAfterInsertion(ve);//调整
return e;
}
/**
* 删除节点的函数
* 1. 如果待删节点左右子树都非空,寻找改节点的后继节点,并把待删节点和待删节点的后继节点替换。此时待删节点会满足下面的两个条件之一
* 2. 待删节点只有一颗非空子树,该非空子树代替待删节点的位置,如果待删节点的颜色位黑色,则调整颜色。(只可能为黑色)
* 3. 待删节点为叶子节点,如果是红色,直接删除,如果是黑色,先进行调整,再删除。
* @param p
*/
public void deleteEntry(Node<T,E> p) {
size--;
if (p.left != null && p.right != null) {// 2. 删除点p的左右子树都非空。
Node<T,E> s = successor(p);// 后继
p.key = s.key;
p.e = s.e;
p = s;
}
Node<T,E> replacement = (p.left != null ? p.left : p.right);
if (replacement != null) {// 1. 删除点p只有一棵子树非空。
replacement.parent = p.parent;
if (p.parent == null) {
root = replacement;
}else if (p == p.parent.left) {
p.parent.left = replacement;
}else {
p.parent.right = replacement;
}
p.left = p.right = p.parent = null;
if (p.color.equals("b")) {
//fixAfterDeletion(replacement);// 调整
setColor(replacement,"b");
}
} else if (p.parent == null) {
root = null;
} else { // 1. 删除点p的左右子树都为空
if (p.color.equals("b")) {
fixAfterDeletion(p);// 调整
}
if (p.parent != null) {//删除p节点
if (p == p.parent.left) {
p.parent.left = null;
}else if (p == p.parent.right) {
p.parent.right = null;
}
p.parent = null;
}
}
}
/**
* 删除节点时的调整函数
* @param x
*/
public void fixAfterDeletion(Node<T,E> x) {
while (x != root && colorOf(x).equals("b")) {
if (x == leftOf(parentOf(x))) {
Node<T,E> sib = rightOf(parentOf(x));
if (colorOf(sib).equals("r")) {
setColor(sib, "b");
setColor(parentOf(x), "r");
rotateLeft(parentOf(x));
sib = rightOf(parentOf(x));
}
if ((leftOf(sib)==null||colorOf(leftOf(sib)).equals("b")) &&
(rightOf(sib)==null||colorOf(rightOf(sib)).equals("b"))){
setColor(sib, "r");
x = parentOf(x);
}else {
if (rightOf(sib)==null||colorOf(rightOf(sib)).equals("b")) {
setColor(leftOf(sib), "b");
setColor(sib, "r");
rotateRight(sib);
sib = rightOf(parentOf(x));
}
setColor(sib, colorOf(parentOf(x)));
setColor(parentOf(x), "b");
setColor(rightOf(sib), "b");
rotateLeft(parentOf(x));
x = root;
}
} else {
Node<T,E> sib = leftOf(parentOf(x));
if (colorOf(sib).equals("r")) {
setColor(sib, "b");
setColor(parentOf(x),"r");
rotateRight(parentOf(x));
sib = leftOf(parentOf(x));
}
if ((rightOf(sib)==null||colorOf(rightOf(sib)) .equals("b")) &&
(leftOf(sib)==null||colorOf(leftOf(sib)).equals("b"))) {
setColor(sib,"r");
x = parentOf(x);
} else {
if (leftOf(sib)==null||colorOf(leftOf(sib)).equals("b")) {
setColor(rightOf(sib),"b");
setColor(sib,"r");
rotateLeft(sib);
sib = leftOf(parentOf(x));
}
setColor(sib, colorOf(parentOf(x)));
setColor(parentOf(x), "b");
setColor(leftOf(sib), "b");
rotateRight(parentOf(x));
x = root;
}
}
}
setColor(x, "b");
}
/***
* 添加节点时的调整函数
* @param x
*/
@SuppressWarnings("unused")
public void fixAfterInsertion(Node<T,E> x) {
x.color = "r";
while (x != null && x != root && x.parent.color == "r") {
if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {//x节点的父节点是x节点的祖父节点的左孩子
Node<T,E> y = rightOf(parentOf(parentOf(x)));
if (colorOf(y) == "r") {//如果y为null,则视为b
setColor(parentOf(x), "b");
setColor(y, "b");
setColor(parentOf(parentOf(x)), "r");
x = parentOf(parentOf(x));
} else {
if (x == rightOf(parentOf(x))) {
x = parentOf(x);
rotateLeft(x);
}
setColor(parentOf(x), "b");
setColor(parentOf(parentOf(x)), "r");
rotateRight(parentOf(parentOf(x)));
}
} else {//x节点的父节点是x节点的祖父节点的右孩子
Node<T,E> y = leftOf(parentOf(parentOf(x)));//y节点为x节点的叔父节点
if (colorOf(y) == "r") {//x节点的叔父节点为红色
setColor(parentOf(x), "b");
setColor(y, "b");
setColor(parentOf(parentOf(x)), "r");
x = parentOf(parentOf(x));
} else {//x节点的叔父节点为黑色
if (x == leftOf(parentOf(x))) {
x = parentOf(x);
rotateRight(x);
}
setColor(parentOf(x), "b");
setColor(parentOf(parentOf(x)), "r");
rotateLeft(parentOf(parentOf(x)));
}
}
}
root.color = "b";
}
private Node<T, E> rightOf(Node<T, E> parentOf) {
// TODO Auto-generated method stub
return parentOf.right;
}
private Node<T, E> leftOf(Node<T, E> parentOf) {
// TODO Auto-generated method stub
return parentOf.left;
}
private void setColor(Node<T, E> y, String string) {
// TODO Auto-generated method stub
y.color=string;
}
private String colorOf(Node<T, E> y) {
// TODO Auto-generated method stub
return y.color;
}
private Node<T,E> parentOf(Node<T, E> x) {
return x.parent;
}
}
二叉树节点类:
package 自平衡二叉搜索树.core;
public class Node<T,E> {
public Integer key;
public E e;
public String color;
public Node<T,E> parent;
public Node<T,E> left;
public Node<T,E> right;
public Node(Integer key, E e) {
super();
this.key = key;
this.e = e;
}
public Node(Integer key, E e, String color, Node<T, E> parent) {
super();
this.key = key;
this.e = e;
this.color = color;
this.parent = parent;
}
public Node(Integer key, E e, String color) {
super();
this.key = key;
this.e = e;
this.color = color;
}
public E setValue(E e) {
return this.e=e;
}
}
打印二叉树的类(必须是层级遍历时用)
package 自平衡二叉搜索树.test;
public class PrintfTree
{
private String v;
private PrintfTree l;
private PrintfTree r;
public PrintfTree(String v){
this.v = v;
}
public void add(PrintfTree the){
if(new Integer(the.v.substring(0,the.v.lastIndexOf("("))) < new Integer(v.substring(0,v.lastIndexOf("(")))){
if(l==null) l = the;
else l.add(the);
}
else{
if(r==null) r = the;
else r.add(the);
}
}
public int getHeight(){
int h = 2;
int hl = l==null? 0 : l.getHeight();
int hr = r==null? 0 : r.getHeight();
return h + Math.max(hl,hr);
}
public int getWidth(){
int w = (""+v).length();
if(l!=null) w += l.getWidth();
if(r!=null) w += r.getWidth();
return w;
}
public void show(){
char[][] buf = new char[getHeight()][getWidth()];
printInBuf(buf, 0, 0);
showBuf(buf);
}
private void showBuf(char[][] x){
for(int i=0; i<x.length; i++){
for(int j=0; j<x[i].length; j++)
System.out.print(x[i][j]==0? ' ':x[i][j]);
System.out.println();
}
}
private void printInBuf(char[][] buf, int x, int y){
String sv = "" + v;
int p1 = l==null? x : l.getRootPos(x);
int p2 = getRootPos(x);
int p3 = r==null? p2 : r.getRootPos(p2+sv.length());
buf[y][p2] = '|';
for(int i=p1; i<=p3; i++) buf[y+1][i]='-';
for(int i=0; i<sv.length(); i++) buf[y+1][p2+i]=sv.charAt(i);
if(p1<p2) buf[y+1][p1] = '/';
if(p3>p2) buf[y+1][p3] = '\\';
if(l!=null) l.printInBuf(buf,x,y+2);
if(r!=null) r.printInBuf(buf,p2+sv.length(),y+2);
}
private int getRootPos(int x){
return l==null? x : x + l.getWidth();
}
}
主测试类
package 自平衡二叉搜索树.test;
import org.junit.Test;
import 自平衡二叉搜索树.core.Node;
import 自平衡二叉搜索树.core.Tree;
public class MainTest {
/***
* 右旋测试
*/
@Test
public void test() {
Node<Integer,Integer> n=new Node<Integer,Integer>(1, 1);
Node<Integer,Integer> n6=new Node<Integer,Integer>(6, 6);
Node<Integer,Integer> n3=new Node<Integer,Integer>(3, 3);
Node<Integer,Integer> n10=new Node<Integer,Integer>(10, 10);
Node<Integer,Integer> n15=new Node<Integer,Integer>(15, 15);
Tree<Integer,Integer> tree=new Tree<>();
tree.root=n10;
tree.root.left=n3;
tree.root.left.left=n;
tree.root.left.right=n6;
tree.root.right=n15;
tree.rotateRight(n10);
tree.preDis2(tree.root);
}
/**
* 左旋测试
*/
@Test
public void test6() {
Node<Integer,Integer> n=new Node<Integer,Integer>(1, 1);
Node<Integer,Integer> n6=new Node<Integer,Integer>(6, 6);
Node<Integer,Integer> n3=new Node<Integer,Integer>(3, 3);
Node<Integer,Integer> n10=new Node<Integer,Integer>(10, 10);
Node<Integer,Integer> n15=new Node<Integer,Integer>(15, 15);
Tree<Integer,Integer> tree=new Tree<>();
tree.root=n3;
tree.root.left=n;
tree.root.right=n10;
tree.root.right.left=n6;
tree.root.right.right=n15;
tree.rotateLeft(n3);
tree.preDis2(tree.root);
}
/**
* get方法测试
*/
@Test
public void test2() {
Node<Integer,Integer> n=new Node<Integer,Integer>(1, 1);
Node<Integer,Integer> n6=new Node<Integer,Integer>(6, 6);
Node<Integer,Integer> n3=new Node<Integer,Integer>(3, 3);
Node<Integer,Integer> n10=new Node<Integer,Integer>(10, 10);
Node<Integer,Integer> n15=new Node<Integer,Integer>(15, 15);
Tree<Integer,Integer> tree=new Tree<>();
tree.root=n3;
tree.root.left=n;
tree.root.right=n10;
tree.root.right.left=n6;
tree.root.right.right=n15;
System.out.println(tree.getE(3));
}
/*
* 调整方法测试
*/
@Test
public void test3() {
Tree<Integer,Integer> tree=new Tree<>();
Node<Integer,Integer> n20=new Node<>(20,20,"b",null);
tree.root=n20;
Node<Integer,Integer> n5=new Node<>(5,5,"r",n20);
Node<Integer,Integer> n32=new Node<>(32,32,"b",n20);
Node<Integer,Integer> n3=new Node<>(3,3,"b",n5);
Node<Integer,Integer> n10=new Node<>(10,10,"b",n5);
Node<Integer,Integer> n8=new Node<>(8,8,"r",n10);
Node<Integer,Integer> n14=new Node<>(14,14,"r",n10);
Node<Integer,Integer> n6=new Node<>(6,6,"r",n8);
Node<Integer,Integer> n45=new Node<>(45,45,"r",n32);
n20.left=n5;
n20.right=n32;
n5.left=n3;
n5.right=n10;
n10.left=n8;
n10.right=n14;
n8.left=n6;
n32.right=n45;
tree.fixAfterInsertion(n6);
tree.preDis(tree.root);
}
/***
* 添加方法测试
*/
@Test
public void test4() {
Tree<Integer,Integer> tree=new Tree<>();
Node<Integer,Integer> n20=new Node<>(20,20,"b",null);
tree.root=n20;
Node<Integer,Integer> n5=new Node<>(5,5,"r",n20);
Node<Integer,Integer> n32=new Node<>(32,32,"b",n20);
Node<Integer,Integer> n3=new Node<>(3,3,"b",n5);
Node<Integer,Integer> n10=new Node<>(10,10,"b",n5);
Node<Integer,Integer> n8=new Node<>(8,8,"r",n10);
Node<Integer,Integer> n14=new Node<>(14,14,"r",n10);
Node<Integer,Integer> n45=new Node<>(45,45,"r",n32);
n20.left=n5;
n20.right=n32;
n5.left=n3;
n5.right=n10;
n10.left=n8;
n10.right=n14;
n32.right=n45;
tree.put(6, 6);
Node<Integer,Integer> n6=new Node<>(6,6,"r");
tree.preDis(tree.root);
/*System.out.println("sdf:"+tree.root.left.right.left.left);*/
}
/**
* 测试寻找后继节点
*/
@Test
public void test7() {
Tree<Integer,Integer> tree=new Tree<>();
Node<Integer,Integer> n15=new Node<>(15,15,"b",null);
tree.root=n15;
Node<Integer,Integer> n12=new Node<>(12,12,"b",n15);
Node<Integer,Integer> n32=new Node<>(32,32,"r",n15);
Node<Integer,Integer> n5=new Node<>(5,5,"b",n12);
Node<Integer,Integer> n13=new Node<>(13,13,"b",n12);
Node<Integer,Integer> n25=new Node<>(25,25,"b",n32);
Node<Integer,Integer> n45=new Node<>(45,45,"b",n32);
Node<Integer,Integer> n19=new Node<>(19,19,"b",n25);
Node<Integer,Integer> n29=new Node<>(29,29,"b",n25);
Node<Integer,Integer> n39=new Node<>(39,39,"b",n45);
Node<Integer,Integer> n60=new Node<>(60,60,"b",n45);
n15.left=n12;
n15.right=n32;
n12.left=n5;
n12.right=n13;
n32.left=n25;
n32.right=n45;
n25.left=n19;
n25.right=n29;
n45.left=n39;
n45.right=n60;
Node<Integer,Integer> p=tree.successor(n5);
System.out.println(p.e);
}
/**
* 删除方法测试·
*/
@Test
public void test8() {
Tree<Integer,Integer> tree=new Tree<>();
Node<Integer,Integer> n9=new Node<>(9,9,"b",null);
tree.root=n9;
Node<Integer,Integer> n4=new Node<>(4,4,"b",n9);
Node<Integer,Integer> n14=new Node<>(14,14,"b",n9);
Node<Integer,Integer> n1=new Node<>(1,1,"r",n4);
Node<Integer,Integer> n6=new Node<>(6,6,"r",n4);
Node<Integer,Integer> n0=new Node<>(0,0,"b",n1);
Node<Integer,Integer> n2=new Node<>(2,2,"b",n1);
Node<Integer,Integer> n3=new Node<>(3,3,"r",n2);
Node<Integer,Integer> n5=new Node<>(5,5,"b",n6);
Node<Integer,Integer> n7=new Node<>(7,7,"b",n6);
Node<Integer,Integer> n12=new Node<>(12,12,"r",n14);
Node<Integer,Integer> n18=new Node<>(18,18,"r",n14);
Node<Integer,Integer> n11=new Node<>(11,11,"b",n12);
Node<Integer,Integer> n13=new Node<>(13,13,"b",n12);
Node<Integer,Integer> n10=new Node<>(10,10,"r",n11);
Node<Integer,Integer> n16=new Node<>(16,16,"b",n18);
Node<Integer,Integer> n19=new Node<>(19,19,"b",n18);
Node<Integer,Integer> n15=new Node<>(15,15,"r",n16);
Node<Integer,Integer> n17=new Node<>(17,17,"r",n16);
n9.left=n4;
n9.right=n14;
n4.left=n1;
n4.right=n6;
n1.left=n0;
n1.right=n2;
n2.right=n3;
n6.left=n5;
n6.right=n7;
n14.left=n12;
n14.right=n18;
n12.left=n11;
n12.right=n13;
n11.left=n10;
n18.left=n16;
n18.right=n19;
n16.left=n15;
n16.right=n17;
tree.cenDis(tree.root);
}
/***
* 删除方法测试
*/
@Test
public void test22() {
Tree<Integer,Integer> tree=new Tree<>();
Node<Integer,Integer> n16=new Node<>(16,16,"b",null);
tree.root=n16;
Node<Integer,Integer> n12=new Node<>(12,12,"b",n16);
Node<Integer,Integer> n32=new Node<>(32,32,"b",n16);
Node<Integer,Integer> n5=new Node<>(5,5,"b",n12);
Node<Integer,Integer> n1=new Node<>(1,1,"b",n5);
Node<Integer,Integer> n6=new Node<>(6,6,"b",n5);
Node<Integer,Integer> n14=new Node<>(14,14,"b",n12);
Node<Integer,Integer> n13=new Node<>(13,13,"b",n14);
Node<Integer,Integer> n15=new Node<>(15,15,"b",n14);
Node<Integer,Integer> n25=new Node<>(25,25,"b",n32);
Node<Integer,Integer> n45=new Node<>(45,45,"b",n32);
Node<Integer,Integer> n19=new Node<>(19,19,"b",n25);
Node<Integer,Integer> n29=new Node<>(29,29,"b",n25);
Node<Integer,Integer> n39=new Node<>(39,39,"b",n45);
Node<Integer,Integer> n60=new Node<>(60,60,"b",n45);
//Node<Integer,Integer> n20=new Node<>(20,20,"r",n19);
Node<Integer,Integer> n28=new Node<>(28,28,"r",n29);
Node<Integer,Integer> n30=new Node<>(30,30,"r",n29);
n16.left=n12;
n16.right=n32;
n12.left=n5;
n12.right=n14;
n32.left=n25;
n32.right=n45;
n25.left=n19;
n25.right=n29;
n29.left=n28;
n29.right=n30;
n45.left=n39;
n45.right=n60;
n5.left=n1;
n5.right=n6;
n14.left=n13;
n14.right=n15;
//n19.right=n20;
tree.cengDis(tree.root);
tree.deleteEntry(n19);
System.out.println();
System.out.println("删除19节点后:");
tree.cengDis(tree.root);
}
}
完结
关于红黑树的删除还有待理解
删除节点有点麻烦