zoukankan      html  css  js  c++  java
  • 数据结构之红黑树(一)

    数据结构之红黑树(一)

      为什么是要使用红黑树? 

      二叉树在平均情况下的运行时间已经是对数级别,为什么还要使用红黑树?原因很简单,二叉树在最坏情况下的查找时间为线性级别,导致这种最坏情况的原因是数据的插入找特定的顺序(从大到小或者从小到大),致使数的高度过大,也就是树的不平衡,因而导致了查询效率的下降。

       因此,改变这种最差情况的查找效率就是使不平衡的树变得平衡。通过一种2-3的查找树可以使树保持平衡,但是处理的情况过于多,实现比较复杂。

      红黑树恰能通过添加节点的颜色来模拟这种2-3树。红黑树与普通二叉树的最大区别在于 ,它在原来的基础上为每个节点设立了颜色。红黑树应该满足如下特性:
        1)红色节点均为左节点
        2)红色节点不能和红色节点相连接
        3)该树是完美黑色平衡,即任意空链接到根节点所经历的黑色节点的数量相同。
      这样以来,仅仅改变树的构造方法,如添加节点和删除节点,而查找以及其他方法均与普通二叉查找树相同。
      不过,红黑树的左旋、右旋和颜色变换等相关方法需要认证理解。

      

    public class RedBlackBST<Key extends Comparable<Key>,Value> {
        private Node root;//红黑树的根节点
        
        private static final boolean RED = true;
        private static final boolean BLACK = false;
        
        private class Node {
            Key key;
            Value value;
            Node left;
            Node right;
            boolean color;//为没个节点设置颜色
            public Node(Key key, Value value, boolean color) {
                super();
                this.key = key;
                this.value = value;
    
                this.color = color;
            }
        }
        
        private boolean isRed(Node node) {
            if(node == null) {
                return false;
            }
            
            return node.color;
        }
        
        /**
         * 添加节点
         * @param key
         * @param value
         */
        public void put(Key key,Value value) {
            root = put(root,key,value);
            root.color = BLACK;
        }
    
        /**
         * 向以h为根节点的子树中添加元素
    
         */
        private Node put(Node h, Key key, Value value) {
            if(h == null) {//递归到树的底部,创建新新节点,返回给上层递归函数,赋值给父节点
                return new Node(key,value,RED);
            }
            //添加元素与二叉树添加元素相同
            int cmp = key.compareTo(h.key);
            if(cmp < 0) {
                h.left = put(h.left,key,value);
            }else if(cmp > 0) {
                h.right = put(h.right,key,value);
            }else {
                h.value = value;
            }
            
            /**
             * 二叉树的变换
             *     这是红黑树区别于二叉树的地方,添加完元素,对数进行变换。
             *         对于不满足红黑树要求的地方进行变换。
             *             主要有以下三种情况,顺序不能改变
             */
            if(isRed(h.right) && !isRed(h.left)) {//情况1:右红左不红,右旋转
                h = rotateLeft(h);
            }
            if(isRed(h.left) && isRed(h.left.left)) {//情况2:左红,左左红,先右旋转,旋转完后满足情况3,进行颜色变换
                h = rotateRight(h);
            }
            
            if(isRed(h.left) && isRed(h.right)) {//情况3:右红左红,变换颜色
                flipColor(h);
            }
            
            return h;
        }
    
        /**
         *变化颜色
         * @param h
         */
        private void flipColor(Node h) {
            h.color = RED;//父节点变为红色
            h.left.color = BLACK;//子节点变为黑色
            h.right.color = BLACK;//子节点变为黑色
        }
    
        /**
         * 右旋转
         * @param h
         * @return
         */
        private Node rotateRight(Node h) {
            Node x = h.left;
            h.left = x.right;
            x.right = h;
            x.color = h.color;
            h.color = RED;
            return x;
        }
    
        /**
         * 左旋转
         * @param h
         * @return
         */
        private Node rotateLeft(Node h) {
            Node x = h.right;
            h.right = x.left;
            x.left = h;
            x.color = h.color;
            h.color = RED;
            return h;
        }
        
    }

      对于树的删除操作,在后续博文中介绍。

  • 相关阅读:
    importlib
    js给kindeditor添加值
    在kindeditor 获取textarea 中 输入的值
    获取lable选中时触发事件
    Django之ModelForm组件
    KindEditor 和 xss过滤
    from 动态显示select数据
    CBV 验证装饰器的使用
    views获取数据 -- request包含的方法
    django -- 自定义simpletag 和 filter
  • 原文地址:https://www.cnblogs.com/gdy1993/p/9332641.html
Copyright © 2011-2022 走看看