算法4第3章红黑树及习题讲解

红黑树是一种自平衡二叉查找树,确保在最坏情况下操作的时间复杂度为O(logN)。通过2-3树的概念帮助理解红黑树,其中2-3树中的节点最多含有2个键和3个子节点。红黑树的特点包括:红链接均为左链接,不允许节点有两个红链接,且每个叶子节点到根节点的黑链接数量相同。本文介绍了红黑树的插入、删除和查找操作,并提供了Java实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉查找树在最坏的情况下性能很差时间复杂度是O(N),本节我们学习一种新的数据结构红黑树
它能保证操作在最坏情况下时间复杂度也是O(logN),无论怎么构造,它都能到达平衡,红黑树结构很复杂,首先我们学习一种叫2-3树的数据结构来帮忙对红黑树的理解。
一般的二叉查找树一个节点只能有一个键两个子节点,在2-3树中一个节点最多可以有两个键3个子节点,左子树中的键都比左边的键小,
中间子树的键大于左边的键小于右边的键,右子树的键都大于右边的键,2-3树的示意图如下

Anatomy of a 2-3 tree
//我们结合下图来理解2-3树的构造过程,

插入的过程总是先把一个节点插入满3个键再进行分离,看右图的过程,先插入A,C,然后插入E,此时节点含3个键进行分裂,A,E各占一个节点,C移到父节点,然后插入H,L后再进行分裂,H移到父节点,然后L,M,P进行分裂,M移到父节点,这时父节点包含CHM3个键,所以父节点继续往上分裂,分裂的过程不会影响数的有序性和平衡性

从图中可以看出不论怎么构造2-3树总能达到平衡
直接用2-3树这种数据结构来达到平衡行也可以实现,但是不太方便,因为要考虑的情况太多
红黑树对2-3树的结构做了些改变,使用简单的结构就可以表达和实现2-3树
红黑树把2-3树中含有两个键的节点想象成2个用红线连接在一起的节点,2-3树中的普通链接用黑线表示,这样红黑树还是一棵二叉树,红黑树和2-3树的对应关系如下

1-1 correspondence between left-leaning red-black BSTs and 2-3 trees
红黑树有以下特征:

1.红链接均为左链接

2.没有节点同时和2个红链接相连,相当于含3个键的2-3树

3.红黑树是完美黑色平衡的,即每个叶子节点到根节点黑链接数量相同
//红黑树的实现过程如下:

public class RedBlackBST<Key extends Comparable<Key>, Value> {

    private static final boolean RED   = true;
    private static final boolean BLACK = false;

    private Node root;     // root of the BST

    // BST helper node data type
    private class Node {
        private Key key;           // key
        private Value val;         // associated data
        private Node left, right;  // links to left and right subtrees
        private boolean color;     // color of parent link,每个节点增加一个颜色值,代表父节点指向自己链接的颜色
        private int size;          // subtree count

        public Node(Key key, Value val, boolean color, int size) {
            this.key = key;
            this.val = val;
            this.color = color;
            this.size = size;
        }
    }
    
    /**
     * Initializes an empty symbol table.
     */
    public RedBlackBST() {
    }

   /***************************************************************************
    *  Node helper methods.
    ***************************************************************************/
    // is node x red; false if x is null ?
    private boolean isRed(Node x) {
        if (x == null) return false;
        return x.color == RED;
    }

    // number of node in subtree rooted at x; 0 if x is null
    private int size(Node x) {
        if (x == null) return 0;
        return x.size;
    }


    /**
     * Returns the number of key-value pairs in this symbol table.
     * @return the number of key-value pairs in this symbol table
     */
    public int size() {
        return size(root);
    }

   /**
     * Is this symbol table empty?
     * @return {@code true} if this symbol table is empty and {@code false} otherwise
     */
    public boolean isEmpty() {
        return root == null;
    }
    
    /**
     * Does this symbol table contain the given key?
     * @param key the key
     * @return {@code true} if this symbol table contains {@code key} and
     *     {@code false} otherwise
     * @throws IllegalArgumentException if {@code key} is {@code null}
     */
    public boolean contains(Key key) {
        return get(key) != null;
    }


   /***************************************************************************
    *  Standard BST search.
    ***************************************************************************/

    /**
     * Returns the value associated with the given key.
     * @param key the key
     * @return the value associated with the given key if the key is in the symbol table
     *     and {@code null} if the key is not in the symbol table
     * @throws IllegalArgumentException if {@code key} is {@code null}
     */
    public Value get(Key key) {
        if (key == null) throw new IllegalArgumentException("argument to get() is null");
        return get(root, key);
    }

    // value associated with the given key in subtree rooted at x; null if no such key
    private Value get(Node x, Key key) {
        while (x != null) {
            int cmp = key.compareTo(x.key);
            if (cmp < 0) x = x.left;
            else if(cmp > 0) x = x.right;
            else  return x.val;
        }
        return null;
    }
    
    /***************************************************************************
     *  Red-black tree insertion.
     ***************************************************************************/

     /**
      * Inserts the specified key-value pair into the symbol table, overwriting the old
      * value with the new value if the symbol table already contains the specified key.
      * Deletes the specified key (and its associated value) from this symbol table
      * if the specified value is {@code null}.
      *
      * @param key the key
      * @param val the value
      * @throws IllegalArgumentException if {@code key} is {@code null}
      */
     public void put(Key key, Value val) {
         if (key == null) throw new IllegalArgumentException("first argument to put() is null");
         if (val == null) {
             delete(key);
             return;
         }

         root = put(root, key, val);
         root.color = BLACK;
         // assert check();
     }
     
     // insert the key-value pair in the subtree rooted at h
     //2-3树在插入过程中总是先往一个节点中插,当节点中键的个数为3时再分裂成2个含有1个键的节点,另一个键移到父节点中,
     //移动后如果父节点变成含3个键的节点,则再分裂父节点
     //红黑树也是一样,插入的节点总是先标记为红色,然后如果不满足红黑树的特征再进行分裂转换
     private Node put(Node h, Key key, Value val) {
         if

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值