• 红黑树之插入java实现


    红黑树的插入有自顶向下和自底向上两种方式,这里的插入实现是自顶向下的方式。

    具体参考的博文地址:http://www.cnblogs.com/xuqiang/archive/2011/05/16/2047001.html

    这篇博文将插入的几种case都讲的很清楚了。这里就直接贴代码了,代码有点丑。

    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

     
  • 相关阅读:
    Pycharm快捷键
    unittest自动化测试框架
    Python简介
    Git工作流介绍
    GitFlow ⼯作流
    go 整分钟开始执行程序
    vue 保留两位小数
    vue 格式化时间戳
    Supervisor-进程守护工具
    为什么计算机语言中的变量名都不能以数字开头呢?
  • 原文地址:https://www.cnblogs.com/chen-jack/p/10236767.html
Copyright © 2020-2023  润新知