美文网首页计算机杂谈程序员Java 杂谈
【红黑树-Java】红黑树,算法导论实现版

【红黑树-Java】红黑树,算法导论实现版

作者: 张照博 | 来源:发表于2018-07-17 17:40 被阅读202次

    正文之前

    不得不说,《算法导论》的伪代码真的是好东西,轻轻一改就是一个船新版本的红黑树具体实现方式。。不多说,直接上码。

    。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 += "\n";
                }
                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("\nDeleted :  "+ z.getKey()+"\n");
        }
    
        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("\nInsert 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】红黑树,算法导论实现版

      本文链接:https://www.haomeiwen.com/subject/ovegpftx.html