紅黑樹之插入java實現

紅黑樹的插入有自頂向下和自底向上兩種方式,這裏的插入實現是自頂向下的方式。

具體參考的博文地址:http://www.cnblogs.com/xuqiang/archive/2011/05/16/2047001.htmlhtml

這篇博文將插入的幾種case都講的很清楚了。這裏就直接貼代碼了,代碼有點醜。node

package 第一章數據結構實現;

public class RBTree {
    TreeNode head;            //樹的頭節點
        //建立紅色的默認節點,可是未設置父節點
    public TreeNode getNode(int val) {
        TreeNode defaultNode  = new TreeNode(val);
        defaultNode.color = Color.RED;    //默認爲紅色
        return defaultNode;
    }
        //打印樹
    public void printTree(TreeNode node) {
        if(head==null) {
            System.out.println("樹是空的,請確認init()方法已經執行!");
            return ;
        }
        if(node==null) return ;
        else {
            //前序遍歷
            System.out.print("節點的值:"+node.val+"    節點的顏色:"+node.color);
            if(node.parent!=null) System.out.println("   節點的父節點:"+node.parent.val);
            else System.out.println("    這是根節點");
            printTree(node.left);
            printTree(node.right);
        }
    }
        //===================================================================================================
        //樹的初始化
        public void init(int[] arr) {
            for(int i=0;i<arr.length;++i) {
                insert(head,null,arr[i],-1);
            }
        }
        //inset  開始插入 ,lr爲0表明left  lr爲1表明right lr爲-1表示是根節點
    public void  insert(TreeNode head,TreeNode parent,int i,int lr) {
            if(head==null) {
                TreeNode x = getNode(i);
                x.parent=parent;
                head = x;        
                if(lr==1) parent.right = head;
                else if(lr==0) parent.left = head;
                insert1(head);
            }
            else {        //遞歸插入
                if(i>head.val)    insert(head.right,head,i,1);
                if(i<head.val)    insert(head.left,head,i,0);
            }
    }
        //case1:插入的節點爲根節點,將插入節點置爲紅色,前期x的父節點x.parent必須肯定下來
    public void insert1(TreeNode  x) {

        if(x.parent==null) {
            x.color = Color.BLACK;
            head = x;                  //將首節點指向x
            return ;
        } else insert2(x);
    }
        //case2:插入的節點不爲根節點
        //且插入的節點的父節點爲黑色的,那麼紅黑樹是不用調節的
    public void insert2(TreeNode x) {    
        if(x.parent.color==Color.BLACK) return ;
        else insert3(x);
    }
        //case3若是插入節點的父節點爲紅色 ,違反父子節點都爲紅色的
        // 若是叔叔節點爲紅色,只需將叔叔節點和父節點同時設爲黑色,同時祖父節點設爲紅色
        //但這會引入新問題,祖父節點和其自身父節點有可能都爲紅色,使用尾遞歸向上上濾
    public void insert3(TreeNode x) {
        TreeNode par = x.parent;    //父節點
        TreeNode gra = par.parent;    //祖父節點
        TreeNode unc = (par==gra.left)? gra.right : gra.left;     //叔叔節點
        if(unc!=null && unc.color==Color.RED) {
            unc.color = Color.BLACK;
            par.color = Color.BLACK;
            gra.color = Color.RED;
            insert1(gra);        //尾遞歸上濾
        } else insert4(x);
    }
        //case4: 若是叔叔節點爲黑色或者null
    public void insert4(TreeNode x) {
        TreeNode par = x.parent;    //父節點
        TreeNode gra = par.parent;    //祖父節點//若是父節點是祖父節點的左節點,但x是父節點的右節點,交換x和其父節點,且x變爲其原父節點的父節點
        if(par==gra.left && x==par.right) {
            gra.left = x;
            x.left = par;
            x.parent = gra;
            par.right = null;
            par.parent = x;
            insert5(par);
        }
        //若是父節點是祖父節點的右節點,可是x是父節點的左節點,交換x和其父節點,且x變爲祖父節點的右節點
        else if(par==gra.right && x==par.left) {
            gra.right = x;
            x.right = par;
            x.parent = gra;
            par.left = null;
            par.parent = x;
            insert5(par);
        }
        else {
            insert5(x);       //由於這個x節點有可能變爲父節點了,因此要在insert5進行判斷是否爲變換後的父節點
        }
    }
    
    public void insert5(TreeNode x) {
            TreeNode par = x.parent;    //父節點
            TreeNode gra = par.parent;    //祖父節點
            TreeNode ggra = gra.parent; //祖父節點的父節點
            if(x==par.left) {
                gra.left = par.right;
                par.right = gra;
                par.parent = ggra;
                gra.parent = par;
                if(gra.left!=null) gra.left.parent = gra;        //若是節點不爲空更新父節點信息
                //ggra.left = par;
                if(ggra==null) head = par;
                else {
                    if(par.val>ggra.val) ggra.right = par;
                    else ggra.left = par;
                }
            }
            else if(x==par.right) {
                //if(x.val==12) System.out.println("12的父節點的左節點:"+par.left.val);
                gra.right = par.left;
                par.left = gra;
                par.parent = ggra;
                gra.parent = par;
                if(gra.right!=null) gra.right.parent = gra;            //要更新父節點信息
                if(ggra==null) head = par;   //根節點要從新指向
                else  {
                    if(par.val>ggra.val) ggra.right = par;
                    else ggra.left = par;
                }
            }
            //顏色變化
            gra.color = Color.RED;
            par.color = Color.BLACK;
    }
    //=======================================================================================================
    public static void main(String[] args) {
        int[] arr = {5,3,1,7,9,6,15,12,14,13};
        RBTree rbt = new RBTree();
        rbt.init(arr);
        rbt.printTree(rbt.head);
    }
        //紅黑樹節點
    private class TreeNode{
        Color color=Color.RED;
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode parent;
        TreeNode(int value) {
            val = value;
        }
    }
        //樹節點枚舉類
    private enum Color{
        RED,BLACK;
    }
    
}
基於int[] arr = {5,3,1,7,9,6,15,12,14,13}構建的紅黑樹的打印的結果以下:

節點的值:7 節點的顏色:BLACK 這是根節點
節點的值:3 節點的顏色:RED 節點的父節點:7
節點的值:1 節點的顏色:BLACK 節點的父節點:3
節點的值:5 節點的顏色:BLACK 節點的父節點:3
節點的值:6 節點的顏色:RED 節點的父節點:5
節點的值:12 節點的顏色:RED 節點的父節點:7
節點的值:9 節點的顏色:BLACK 節點的父節點:12
節點的值:14 節點的顏色:BLACK 節點的父節點:12
節點的值:13 節點的顏色:RED 節點的父節點:14
節點的值:15 節點的顏色:RED 節點的父節點:14數據結構

相關文章
相關標籤/搜索