数据结构——红黑树的特性及实现(二)

简介: 数据结构——红黑树的特性及实现

5.2 向底部的2-结点插入新键


用和二叉查找树相同的方式向一棵红黑树中插入一个新键,会在树的底部新增一个结点(可以保证有序性),唯一区别的地方是我们会用红链接将新结点和它的父结点相连。如果它的父结点是一个2-结点,那么刚才讨论的两种方式仍然适用。

1.png

5.3 向一棵双键树(即一个3-结点)中插入新键


这种情况有可以分为三种子情况:

新键大于原树中的两个键

1.png

新键介于原数中两个键之间

1.png

5.4 向树底部的3-结点插入新键


假设在树的底部的一个3-结点下加入一个新的结点。前面我们所讲的3种情况都会出现。指向新结点的链接可能是 3-结点的右链接(此时我们只需要转换颜色即可),或是左链接(此时我们需要进行右旋转然后再转换),或是中链接(此时需要先左旋转然后再右旋转,最后转换颜色)。颜色转换会使中间结点的颜色变红,相当于将它送入了父结点。这意味着父结点中继续插入一个新键,我们只需要使用相同的方法解决即可,直到遇到一个2-结点或者根结点为止。

1.png

6. 根结点的颜色总是黑色


之前我们介绍结点API的时候,在结点Node对象中color属性表示的是父结点指向当前结点的连接的颜色,由于根结点不存在父结点,所以每次插入操作后,我们都需要把根结点的颜色设置为黑色。


7. 红黑树的实现


7.1 红黑树的API设计


类名 RedBlackTree, Value>
构造方法 RedBlackTree():创建RedBlackTree对象
成员方法

1.private boolean isRed(Node x):判断当前结点的父指向链接是否为红色

2.private Node rotateLeft(Node h):左旋调整

3.private Node rotateRight(Node h):右旋调整

4.private void flflipColors(Node h):颜色反转,相当于完成拆分4-结点

5.public void put(Key key, Value val):在整个树上完成插入操作

6.private Node put(Node h, Key key, Value val):在指定树中,完成插入操作,并返回添加元素后新的树

7.public Value get(Key key):根据key,从树中找出对应的值

8.private Value get(Node x, Key key):从指定的树x中,找出key对应的值

9.public int size():获取树中元素的个数

成员变量 1.private Node root : 记录根结点
2.private int N:记录树中元素的个数
3.private static fifinal boolean RED:红色链接标识
4.private static fifinal boolean BLACK:黑色链接标识

7.2 代码


public class RedBlackTree<Key extends Comparable<Key>, Value> {
    //根节点
    private Node root;
    //记录树中元素的个数
    private int N;
    //红色链接
    private static final boolean RED = true;
    //黑色链接
    private static final boolean BLACK = false;
    //结点类
    private class Node {
        //存储键
        public Key key;
        //存储值
        private Value value;
        //记录左子结点
        public Node left;
        //记录右子结点
        public Node right;
        //由其父结点指向它的链接的颜色
        public boolean color;
        public Node(Key key, Value value, Node left, Node right, boolean color) {
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
            this.color = color;
        }
    }
    //获取树中元素的个数
    public int size() {
        return N;
    }
    /**
     * 判断当前节点的父指向链接是否为红色
     *
     * @param x
     * @return
     */
    private boolean isRed(Node x) {
        if (x==null){
            return false;
        }
        return x.color==RED;
    }
    /**
     * 左旋转
     *
     * @param h
     * @return
     */
    private Node rotateLeft(Node h) {
        //找到h结点的右子结点x
        Node x = h.right;
        //找到x结点的左子结点,让x结点的左子结点称为h结点的右子结点
        h.right = x.left;
        //让h结点称为x结点的左子结点
        x.left = h;
        //让x结点的color属性变为h结点的color属性
        x.color = h.color;
        //让h结点的color属性变为RED
        h.color = RED;
        return x;
    }
    /**
     * 右旋
     *
     * @param h
     * @return
     */
    private Node rotateRight(Node h) {
        //找到h结点的左子结点 x
        Node x = h.left;
        //让x结点的右子结点成为h结点的左子结点
        h.left = x.right;
        //让h结点成为x结点的右子结点
        x.right = h;
        //让x结点的color属性变为h结点的color属性
        x.color = h.color;
        //让h结点的color属性为RED
        h.color = RED;
        return x;
    }
    /**
     * 颜色反转,相当于完成拆分4-节点
     *
     * @param h
     */
    private void flipColors(Node h) {
        //当前结点变为红色
        h.color = RED;
        //左子结点和右子结点变为黑色
        h.left.color=BLACK;
        h.right.color = BLACK;
    }
    /**
     * 在整个树上完成插入操作
     *
     * @param key
     * @param val
     */
    public void put(Key key, Value val) {
        root = put(root,key,val);
        //根结点的颜色总是黑色
        root.color = RED;
    }
    /**
     * 在指定树中,完成插入操作,并返回添加元素后新的树
     *
     * @param h
     * @param key
     * @param val
     */
    private Node put(Node h, Key key, Value val) {
        //判断h是否为空,如果为空则直接返回一个红色的结点就可以了
        if (h == null){
            //数量+1
            N++;
            return new Node(key,val,null,null,RED);
        }
        //比较h结点的键和key的大小
        int cmp = key.compareTo(h.key);
        if (cmp<0){
            //继续往左
            h.left = put(h.left,key,val);
        }else if (cmp>0){
            //继续往右
            h.right = put(h.right,key,val);
        }else{
            //发生值的替换
            h.value = val;
        }
        //进行左旋:当当前结点h的左子结点为黑色,右子结点为红色,需要左旋
        if (isRed(h.right) && !isRed(h.left)){
            h = rotateLeft(h);
        }
        //进行右旋:当当前结点h的左子结点和左子结点的左子结点都为红色,需要右旋
        if (isRed(h.left) && isRed(h.left.left)){
            rotateRight(h);
        }
        //颜色反转:当前结点的左子结点和右子结点都为红色时,需要颜色反转
        if (isRed(h.left) && isRed(h.right)){
            flipColors(h);
        }
        return h;
    }
    //根据key,从树中找出对应的值
    public Value get(Key key) {
        return get(root,key);
    }
    //从指定的树x中,查找key对应的值
    public Value get(Node x, Key key) {
        if (x == null){
            return null;
        }
        //比较x结点的键和key的大小
        int cmp = key.compareTo(x.key);
        if (cmp<0){
            return get(x.left,key);
        }else if (cmp>0){
            return get(x.right,key);
        }else{
            return x.value;
        }
    }
}

7.3 测试代码


public class RedBlackTreeTest {
    public static void main(String[] args) {
        //创建红黑树
        RedBlackTree<String,String> tree = new RedBlackTree<>();
        //往树中插入元素
        tree.put("1","张三");
        tree.put("2","李四");
        tree.put("3","王五");
        //从树中获取元素
        String r1 = tree.get("1");
        System.out.println(r1);
        String r2 = tree.get("2");
        System.out.println(r2);
        String r3 = tree.get("3");
        System.out.println(r3);
    }
}


相关文章
|
6天前
|
算法 C++
【数据结构与算法】—— 手撕红黑树
【数据结构与算法】—— 手撕红黑树
|
6天前
|
存储 Java 数据库
手撕红黑树 - 聊聊这个基本却又重要的数据结构
手撕红黑树 - 聊聊这个基本却又重要的数据结构
22 0
|
6天前
|
存储 关系型数据库 数据库
【数据结构】—红黑树(C++实现)
【数据结构】—红黑树(C++实现)
|
7月前
|
存储 Java 数据库
【红黑树数据结构及其应用】
【红黑树数据结构及其应用】
|
7月前
|
存储
数据结构之二叉查找树(Binary Search Tree)和红黑树(Red Black Tree)
二叉查找树又可以称之为 : 二叉搜索树 , 二叉排序树 , 它或者是一棵空树,或者是具有下列性质的二叉树:若它的左子树不空,则左子树上所有结点的值均小于它的根节点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树。二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势 , 下图中这棵树,就是一棵典型的二叉查找树
118 1
|
7月前
|
关系型数据库
|
6天前
|
存储 算法 Java
数据结构/C++:红黑树
数据结构/C++:红黑树
15 3
|
6天前
|
存储 缓存 算法
数据结构与算法 树(B树,B+树,红黑树待完善)
数据结构与算法 树(B树,B+树,红黑树待完善)
20 0
|
6天前
数据结构===红黑树
红黑树是平衡二叉搜索树,关键点在于其满足5个性质,包括根节点为黑,叶子为黑,红色节点不能相邻且路径上黑节点数相等。插入和删除时结合左旋、右旋操作。插入时,针对叔叔节点颜色(红或黑),参照AVL树的失衡处理,分为4种情况,并调整颜色策略。删除操作同样复杂,涉及节点替换和颜色调整。
13 1
|
6天前
|
测试技术 数据库
[数据结构]-红黑树
[数据结构]-红黑树