zoukankan      html  css  js  c++  java
  • 3.3 平衡查找树

    希望找到一种数据结构,能够保证所有操作(范围查找除外)均能够在对数时间内完成操作,以便改变二叉查找树的不足。

    平衡查找树Balance Search Tree

    一.2-3查找树

    1.数据结构:每个结点允许1个或者两个key

    (1)2-node:一个键,两个child。左子树小于该节点,右子树大于该节点。

    (2)3-node:两个键,三个child。左子树小于两个节点,右子树大于两个节点,中间的子树在两个节点之间。

    这个限定称为symmetric order

    2.完美平衡(Perfect balance):所有空链接到根结点的距离应该相等。

    3.查找的思路:根据2-3查找树的概念,从根开始递归的查找该元素。和二叉查找树类似。

    4.插入的思路:(保持完美平衡和symmetric order)

    (1)如果在底部的2-node中插入,查找key应该插入的位置,然后将2-node变为3-node

    (2)如果在底部的3-node中插入

      1)在3-node中增加一个key,暂时形成4-node

      2)将4-node中中间的一个移动到父结点中

      3)如果不满足2-3的结构的话,重复上面的过程

      4)如果已经到达了根结点,并且根结点是一个4-node,则将它拆分为3个2-node,也就是使得树的层次+1

    5.三种情况举例:

    (1)插入K(2-node变为3-node)

    -------------》

    (2)插入Z(临时4-node移动到父结点)

    --------------------》

    (3)插入L(根结点都满了,增加树的高度)

    --------》------》

    6.说明:

    (1)树的高度。最坏的情况,全为2-nodes,性能是lgN。最好的情况,全为3-nodes,性能是logN/log3。

    (2)对于million结点来说,树的高度在12到20之间。对于billion结点来说,高度在18到30之间。

    (3)可以保证clgN的性能。

    (4)直接的实现很复杂

    二.红黑二叉查找树red-black BSTs

    1.基本思想:利用标准的二叉查找树和一些额外的信息来表示2-3树

    (1)红链接将2-node连接起来构成3-node

    (2)黑链接则是2-3树中的普通链接

    (3)3-node中较大的key是root

    2.另一个等价的定义:红黑树(left-leaning red-black BST)是一个含有红黑链接的特殊的二叉查找树,满足:

    (1)没有一个结点同时和两个红链接相连

    (2)该树是完美黑色平衡。即任意空链接到根结点的路径上的黑链接数量相同

    (3)红链接均为链接。

    3.从上面的分析可以,红黑树是 2-3树的一种等价的简单的实现。

    4.查找。和普通的BST类似(不考虑颜色),但是由于具有更好的平衡性,红黑树有更快的查找速度。

       很多其他的操作(ceiling,selection等),也和普通的BST类似。

    5.用BST表示红黑树。颜色表示,在普通BST的实现中给每个Node加上一个颜色(布尔值),表示父链接的颜色是红(true)/黑(false)。

    6.左旋转。将一个右倾斜的红链接变为左倾斜。依旧维持了symmetric order和完美黑色平衡。

    --------------------》

        //左旋转,将右倾斜变为左倾斜
        Node rotateLeft(Node h) {
            //结点关系
            Node x=h.right;
            h.right=x.left;
            x.left=h;
            //颜色
            x.color=h.color;
            h.color=RED;
            return x;    
        }
    View Code

    7.右旋转。作为过渡的步骤。

    ---------------》

        //右旋转
        Node rotateRight(Node h) {
            Node x=h.left;
            h.left=x.right;
            x.right=h;
            x.color=h.color;
            h.color=RED;
            return x;
        }
    View Code

    8.颜色反转。重绘颜色来分开一个临时的4-node。

    ----------------》

        private void flipColors(Node h) {
            h.color=RED;
            h.left.color=BLACK;
            h.right.color=BLACK;
        }
    View Code

    9.插入。通过上述基本操作可以使得2-3树和红黑树一一对应。

    向一个3-node中插入新键的三种情况(算法的基础)

    10.例子(完整的例子见算法P282)

    ---》-->-->-->

    11.插入的思路:(以下结论对上述讨论的所有情况均满足)

    (1)右边child是红色,左边child是黑色:左旋转

    (2)左边child,左左边grandchild均为红色:右旋转

    (3)children均是红色:颜色反转

    12.插入操作的代码实现

    package com.cx.serch;
    
    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,right;
            int count;
            //父链接的颜色
            boolean color;
            public Node(Key key,Value value,int count,boolean color) {
                this.key=key;
                this.value=value;
                this.count=count;
                this.color=color;
            }
        }
        /**
         *    实现size()方法
         */
        public int size() {
            return size(root);
        }
        private int size(Node x) {
            if(x==null) return 0;
            return x.count;
        }
        /**
         *    实现put()方法
         */
        public void put(Key key,Value value) {
            root=put(root, key, value);
            root.color=BLACK;
        }
        //插入元素操作
        private Node put(Node h,Key key,Value value) {
            //在底层插入时,先插入红链接
            if(h==null) return new Node(key,value,1,RED);
            //普通BST的插入操作
            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)) h=rotateLeft(h);
            //左子结点和左左子结点为红,右旋转
            if(isRed(h.left) && isRed(h.left.left)) h=rotateRight(h);
            //左右子结点均为红色,颜色转换
            if(isRed(h.left) && isRed(h.right)) flipColors(h);
        
            h.count=1+size(h.left)+size(h.right);
            return h;
        }
        
        private boolean isRed(Node x) {
            if(x==null) return false;
            return x.color==RED;
        }
        
        //左旋转,将右倾斜变为左倾斜
        Node rotateLeft(Node h) {
            //结点关系
            Node x=h.right;
            h.right=x.left;
            x.left=h;
            //颜色
            x.color=h.color;
            h.color=RED;
            return x;    
        }
        //右旋转
        Node rotateRight(Node h) {
            Node x=h.left;
            h.left=x.right;
            x.right=h;
            x.color=h.color;
            h.color=RED;
            return x;
        }
        //反转颜色
        private void flipColors(Node h) {
            h.color=RED;
            h.left.color=BLACK;
            h.right.color=BLACK;
        }
        
    }
    View Code

    13.说明

    (1)红黑树在最坏情况下,树的高度不大于2lgN

    (2)在应用中,红黑树的盖度~1.00lgN

    (3)具有lgN的性能保障

    14.红黑树的用途:

    (1)Java:java.util.TreeMap,java.util.TreeSet

    (2)C++ STL:map,multimap,mulyiset

    (3)Linux内核:完全公平调度 

     三.B树

    1.用在数据量较大,外存占主要部分时,B树因其读磁盘次数少,而具有更快的速度。

    2.类似2-3树,但是我们允许每个结点有更多的keys,当结点满的时候,会分解为2个,所以每个结点都在半满和满之间。

    3.在B树中插入或查找m阶N个键需要

      实际中,M=1024,N=62billion,则最多为4次探索磁盘

    4.B树用途:数据库:sql、Oracle、DB2

  • 相关阅读:
    Pandas DataFrame操作
    Pandas Series数据结构基本操作
    Locally weighted regression algorithm
    Python Numpy线性代数操作
    Python Numpy 矩阵级基本操作(2)
    分布式锁1 Java常用技术方案(转)
    设计模式
    设计模式
    设计模式
    Lock和synchronized比较详解(转)
  • 原文地址:https://www.cnblogs.com/sunnyCx/p/8243097.html
Copyright © 2011-2022 走看看