红黑树-Java红黑树,算法导论实现版
Posted 数据结构与算法
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了红黑树-Java红黑树,算法导论实现版相关的知识,希望对你有一定的参考价值。
作者丨HustWolf
https://www.jianshu.com/p/263c49cfd37d
不得不说,《算法导论》的伪代码真的是好东西,轻轻一改就是一个船新版本的红黑树具体实现方式。。不多说,直接上码。
。emm 放一个我的小surprise~
正文
import java.util.Arrays;
import java.util.Random;
import java.util.LinkedList;
import java.util.Queue;
class node{
private int key;
node leftChild;
node rightChild;
node parent;
String color = Tree.RED;
node(){};
node(int x){
this.parent = Tree.nil;
this.rightChild = Tree.nil;
this.leftChild = Tree.nil;
this.key=x;
}
public int getKey(){
return this.key;
}
}
class Tree{
public static String RED = "RED";
public static String BLACK = "BLACK";
node root;
int size;
public static node nil = new node(-1);
Tree(){
this.size = 0;
this.root = Tree.nil;
nil.color = Tree.BLACK;
}
node getRoot(){
return this.root;
}
public String toString() {
System.out.println("输出树形: ");
Queue<node> queue = new LinkedList<>();
String out = "";
queue.add(this.root);
int x=-10000;
while (!queue.isEmpty()) {
node s = queue.poll();
if (s.getKey()<x) {
out += "
";
}
x=s.getKey();
out += (s.getKey() + " ");
if (s.leftChild != Tree.nil)
queue.add(s.leftChild);
if (s.rightChild != Tree.nil)
queue.add(s.rightChild);
}
return out;
}
// public node minNode(Tree tree){
// node parent = tree.root;
// while(parent.leftChild!=Tree.nil)
// parent=parent.leftChild;
// return parent;
// }
// public node maxNode(Tree tree){
// node parent = tree.root;
// while(parent.rightChild!=Tree.nil)
// parent=parent.rightChild;
// return parent;
// }
}
public class TestTree{
private static node __findNode(node par,int z){
if (par==Tree.nil || par.getKey() == z)
return par;
if (z<par.getKey()) return __findNode(par.leftChild,z);
else return __findNode(par.rightChild,z);
}
static node findNode(Tree tree,int z){
node par = tree.getRoot();
return __findNode(par,z);
}
static void RB_TRANSPLANT(Tree tree, node u, node v){
if (u.parent == Tree.nil) tree.root = v;
else if (u == u.parent.leftChild){
u.parent.leftChild = v;
}
else {
u.parent.rightChild = v;
}
//this is the BST's condition, but in RB we don't need this, because Tree.nil is always a node instead of NULL
// if (v!=Tree.nil)
// u.parent = v.parent;
}
static void RB_DELETE_FIXUP(Tree tree, node x){
while (x != Tree.nil && x.color.equals(Tree.BLACK)){
if (x == x.parent.leftChild){
node w = x.parent.rightChild;
if (w.color.equals(Tree.RED)){
w.color = Tree.BLACK;
x.parent.color = Tree.RED;
LEFT_RORATE(tree,x.parent);
}
if (w.leftChild.color.equals(Tree.BLACK) && w.rightChild.color.equals(Tree.BLACK)){
w.color = Tree.RED;
x = x.parent;
}
else if (w.rightChild.color.equals(Tree.BLACK)){
w.leftChild.color = Tree.BLACK;
w.color = Tree.RED;
RIGHT_RORATE(tree,w);
w = x.parent.rightChild;
}
w.color = x.parent.color;
x.parent.color = Tree.BLACK;
w.rightChild.color = Tree.BLACK;
LEFT_RORATE(tree,x.parent);
x = tree.getRoot();
}
else {
node w = x.parent.leftChild;
if (w.color.equals(Tree.RED)){
w.color = Tree.BLACK;
x.parent.color = Tree.RED;
RIGHT_RORATE(tree,x.parent);
}
if (w.rightChild.color.equals(Tree.BLACK) && w.leftChild.color.equals(Tree.BLACK)){
w.color = Tree.RED;
x = x.parent;
}
else if (w.leftChild.color.equals(Tree.BLACK)){
w.rightChild.color = Tree.BLACK;
w.color = Tree.RED;
LEFT_RORATE(tree,w);
w = x.parent.leftChild;
}
w.color = x.parent.color;
x.parent.color = Tree.BLACK;
w.leftChild.color = Tree.BLACK;
RIGHT_RORATE(tree,x.parent);
x = tree.getRoot();
}
}
x.color = Tree.BLACK;
}
static void deleteFromTree(Tree tree, node z){
tree.size-=1;
node y = z;
String originColor = y.color;
node x = y;
if (z.leftChild==Tree.nil) {
x = z.rightChild;
RB_TRANSPLANT(tree, z, z.rightChild);
}
else if (z.rightChild==Tree.nil) {
x = z.leftChild;
RB_TRANSPLANT(tree, z, z.leftChild);
}
else {
y = minNode(z.rightChild);
originColor = y.color;
x = y.rightChild;
if (y.parent == z){
x.parent = y;
}
else{
RB_TRANSPLANT(tree,y,y.rightChild);
y.rightChild = z.rightChild;
y.rightChild.parent = y;
}
RB_TRANSPLANT(tree,z,y);
y.leftChild = z.leftChild;
y.leftChild.parent = y;
y.color = z.color;
}
if (originColor.equals(Tree.BLACK)){
RB_DELETE_FIXUP(tree,x);
}
System.out.println("
Deleted : "+ z.getKey()+"
");
}
private static node minNode(node no){
node x = no;
while (x.leftChild!=Tree.nil)
x=x.leftChild;
return x;
}
public static void insertSort(int []arr, int n){
for (int i = 1; i < n; ++i)
{
int e = arr[i];
int j=i;
for (; j > 0; --j)
{
if (e < arr[j-1])
arr[j] = arr[j-1];
else
break;
}
arr[j] = e;
}
}
public static void LEFT_RORATE(Tree T, node x){
node y = x.rightChild;
x.rightChild = y.leftChild;
if (y.leftChild != Tree.nil){
y.leftChild.parent = x;
}
y.parent = x.parent;
if (x.parent == Tree.nil)
T.root = y;
else if (x.parent.leftChild == x)
x.parent.leftChild = y;
else x.parent.rightChild = y;
y.leftChild = x;
x.parent = y;
System.out.println("Left Rorate :" + x.getKey()+"<--->"+y.getKey());
}
public static void RIGHT_RORATE(Tree T, node y){
node x = y.leftChild;
y.leftChild = x.rightChild;
if (x.rightChild!=Tree.nil)
x.rightChild.parent = y;
x.parent = y.parent;
if (y.parent == Tree.nil)
T.root = x;
else if (y.parent.leftChild == y)
y.parent.leftChild = x;
else y.parent.rightChild = x;
x.rightChild = y;
y.parent = x;
System.out.println("Right Rorate :" + y.getKey()+"<--->"+x.getKey());
}
static void RB_INSERT_FIXUP(Tree tree,node z){
//while the node's father'color is RED, and the node's color is also RED which we focus;
while(z.parent.color.equals(Tree.RED)){
// now if the node's father is the left node ;
if (z.parent ==z.parent.parent.leftChild){
// we get the node'grandfather's another son node whose name is y, and it is the node's uncle we focus
node y = z.parent.parent.rightChild;
//if uncle node's color is RED:
if (y.color.equals(Tree.RED)){
// father node's color change to BLACK
z.parent.color = Tree.BLACK;
//uncle node's color change to BLACK;
y.color = Tree.BLACK;
//and grandfather node's color change to RED, now Nature 4 is OK!
z.parent.parent.color = Tree.RED;
// then we can focus on grandfather node now!
z = z.parent.parent;
}
// if uncle node'color is BLACK and the node we focus is the right node of its father:
else if (z==z.parent.rightChild){
//we now focus on its father
z=z.parent;
// Rorate left of the new focus node;
LEFT_RORATE(tree,z);
}
// if uncle node'color is BLACK and the node we focus is the left node of its father:
else {
// change the father'color to BLACK;
z.parent.color = Tree.BLACK;
//change the grandfather node 's color to RED;
z.parent.parent.color = Tree.RED;
// Rorate right of the grandfather:
RIGHT_RORATE(tree, z.parent.parent);
}
}
else {
node y = z.parent.parent.leftChild;
if (y.color.equals(Tree.RED)){
z.parent.color = Tree.BLACK;
y.color = Tree.BLACK;
z.parent.parent.color = Tree.RED;
z = z.parent.parent;
}
else if (z==z.parent.leftChild){
z=z.parent;
RIGHT_RORATE(tree,z);
}
else{
z.parent.color = Tree.BLACK;
z.parent.parent.color = Tree.RED;
LEFT_RORATE(tree,z.parent.parent);
}
}
}
tree.root.color = Tree.BLACK;
}
public static void insertToTree(Tree tree,int x){
System.out.println("
Insert into the Tree : "+x);
tree.size+=1;
node newnode = new node(x);
newnode.color = Tree.RED;
node tmp = tree.getRoot();
if ( tmp== Tree.nil) {
tree.root = newnode;
tree.root.color = Tree.BLACK;
tree.root.parent =Tree.nil;
return;
}
while(tmp!=Tree.nil) {
if (x < tmp.getKey()) {
if (tmp.leftChild==Tree.nil) {
newnode.parent = tmp;
newnode.leftChild = Tree.nil;
tmp.leftChild = newnode;
break;
}
else
tmp = tmp.leftChild;
}
else {
if ( tmp.rightChild==Tree.nil) {
newnode.parent = tmp;
newnode.rightChild =Tree.nil;
tmp.rightChild = newnode;
break;
}
else
tmp = tmp.rightChild;
}
}
RB_INSERT_FIXUP(tree,newnode);
}
public static Tree generateTree(int[] arr){
Tree tree = new Tree();
// insertSort(arr,arr.length);
insertToTree(tree,arr[arr.length/2]);
for (int i=0;i<arr.length;++i) {
if (i!=arr.length/2) {
insertToTree(tree,arr[i]);
}
}
return tree;
}
public static void main(String[] args) {
double start = System.currentTimeMillis();
Random rdm = new Random(System.currentTimeMillis());
int len = 20;
int [] randomArr = new int[len];
for(int i=0;i<len;i++)
randomArr[i] = Math.abs(rdm.nextInt())%(len*5) +1;
Tree tree = generateTree(randomArr);
System.out.println(Arrays.toString(randomArr));
System.out.println(tree.toString());
deleteFromTree(tree,findNode(tree,randomArr[Math.abs(rdm.nextInt())%(tree.size-2)+1]));
System.out.println(tree.toString());
insertToTree(tree,Math.abs(rdm.nextInt())%(len*5) +1);
System.out.println(tree.toString());
double end = System.currentTimeMillis();
System.out.println("Usage of Time: "+(end-start));
}
}
基本没啥问题,在原有的二叉搜索树上增加了两个修复方法,另外就是每个节点新增了一个Color属性,还有就是用黑色的Tree.nil全面替代了NULL这个东西,实在是妙不可言!!我他么就不明白了,以前的计算机科学家脑子怎么长的??这么逆天的数据结构都能想出来?!!
运行结果(Output):
Insert into the Tree : 82
Insert into the Tree : 98
Insert into the Tree : 15
Insert into the Tree : 8
Insert into the Tree : 1
Right Rorate :15<--->8
Insert into the Tree : 73
Insert into the Tree : 15
Right Rorate :73<--->15
Left Rorate :15<--->15
Insert into the Tree : 28
Left Rorate :8<--->15
Right Rorate :82<--->15
Insert into the Tree : 90
Insert into the Tree : 2
Insert into the Tree : 47
Left Rorate :28<--->47
Right Rorate :73<--->47
Insert into the Tree : 42
Insert into the Tree : 19
Insert into the Tree : 81
Insert into the Tree : 60
Insert into the Tree : 75
Left Rorate :47<--->73
Right Rorate :82<--->73
Insert into the Tree : 45
Insert into the Tree : 48
Insert into the Tree : 45
Left Rorate :42<--->45
Insert into the Tree : 54
Left Rorate :48<--->54
Right Rorate :60<--->54
[98, 15, 8, 1, 73, 15, 28, 90, 2, 47, 82, 42, 19, 81, 60, 75, 45, 48, 45, 54]
输出树形:
15
8 73
1 15 47 82
2 28 54 81 98
19 45 48 60 75 90
42 45
Deleted : 90
输出树形:
15
8 73
1 15 47 82
2 28 54 81 98
19 45 48 60 75
42 45
Insert into the Tree : 51
输出树形:
15
8 73
1 15 47 82
2 28 54 81 98
19 45 48 60 75
42 45 51
Usage of Time: 3.0
Process finished with exit code 0
正文之后
溜了溜了,今晚准备骑单车征服长江大桥!emm 值得期待!!
推荐↓↓↓
长
按
关
注
以上是关于红黑树-Java红黑树,算法导论实现版的主要内容,如果未能解决你的问题,请参考以下文章