红黑树

红黑树(Red Black Tree) 是一种自平衡二叉查找树,典型用途是实现关联数组。

它是在1972年由Rudolf Bayer发明的,当时被称为平衡二叉B树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的“红黑树”。

约束性质:

    1、每一个节点非红即黑

    2、根节点永远为黑的

    3、每一个叶子节点都是黑色的(NLL,空节点)

    4、每个红色节点的两个子节点都是黑色的(从每个叶子到根的所有路径上不能有两个连续的红色节点)

    5、从任意一个节点到其每个叶子节点的所有路径都包含相同数目的黑色节点

    这些约束性质强制了红黑树的关键性质,从根到叶子节点的最长可能路径不多于最短可能路径的两倍长(第四五条),这条性质保证了这个树在高度上大致上时平衡的,因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例。

    叶子节点不保存数据只作为树在此结束的标志。

    红黑色只需要每个节点中1 bit的存储空间

    红黑树在函数式编程中也特别有用,在这里它们是最常用的持久数据结构之一,它们用来构造关联数组和集合,在突变之后它们能保持为以前的版本。除了O(log n)的时间之外,红黑树的持久版本对每次插入或删除需要O(log n)的空间。


当在对红黑树进行插入和删除等操作时,对树做了修改可能会破坏红黑树的性质。为了继续保持红黑树的性质,可以通过对结点进行重新着色,以及对树进行相关的旋转操作,即通过修改树中某些结点的颜色及指针结构,来达到对红黑树进行插入或删除结点等操作后继续保持它的性质或平衡的目的。

左旋
右旋

红黑树的修正:

    1、当前节点为红色,且父节点和叔父节点为红色,那么将父节点以及叔叔节点涂黑,将祖父节点涂红。

    2、当前节点为红色,并且是右子叶,父节点为红,且叔父节点为黑,那么以当前节点为基准进行左旋

    3、   当前节点为红色,并且为左子叶,父节点为红且叔父节点为黑,那么以父节点为基准进行右旋。交换祖父与父节点颜色


红黑树的插入

    插入节点为红色(如果我们插入的是黑色节点,那就违反了性质五,需要进行大规模调整)

    1、当插入节点是根节点时,直接涂黑插入

    2、当插入节点父节点为黑色时,直接插入

    其他情况先插入,再修正。


红黑树的删除

    1、当删除的元素为红时,对五条性质没有影响,直接删除

    2、当删除节点为根节点时,直接删除

    3、如果被删元素只有一个子节点,则其子节点顶替其位置,只交换值,不换颜色

    4、如果有两个子节点,这时候就可以把被删除元素的右支的最小节点(被删除元素右支的最左边的节点)和被删除元素互换,我们把被删除元素右支的最左边的节点称之为后继节点(后继元素)、只交换值,不换颜色

    然后对其进行修正


##Code

```

package com.gdufe.binarysearchtree;

import java.io.File;

import java.util.Scanner;

public class RedBlackTree, Value> {

    Node root; // 维护根节点

    final static boolean RED = true;

    final static boolean BLACK = false;

    class Node { // 二叉树的结点

        Key key;

        Value value;

        boolean color;

        Node left, right;

        public Node(Key key, Value value, boolean color) { // 初始化结点

            this.key = key;

            this.value = value;

            this.color = color;

        }

    }

    public Value get(Key key) {

        return get(root, key);

    }

    // 右旋

    public Node rotateRight(Node h) {

        Node x = h.left;

        h.left = x.right;

        x.right = h;

        x.color = h.color;

        h.color = RED;

        return x;

    }

    // 左旋

    public Node rotateLeft(Node h) {

        Node x = h.right;

        h.right = x.left;

        x.left = h;

        x.color = h.color;

        h.color = RED;

        return x;

    }

    // 变色处理

    public void flipColors(Node h) {

        h.left.color = BLACK;

        h.right.color = BLACK;

        h.color = RED;

    }

    public boolean isRed(Node x){

        if(x==null) return false;

        else return x.color;

    }

    public Value get(Node x, Key key) {

        if (x == null)

            return null;

        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;

    }

    public void put(Key key, Value value) {

        root = put(root, key, value);

        root.color = BLACK;

    }

    public Node put(Node x, Key key, Value value) {

        if (x == null)

            return new Node(key, value, RED); // 添加的结点链接为红色

        int cmp = key.compareTo(x.key);

        if (cmp < 0)

            x.left = put(x.left, key, value);

        else if (cmp > 0)

            x.right = put(x.right, key, value);

        else {

            x.value = value;

        }

        // 判断是否需要左旋,右旋,变色操作

        if (x != null) {

            if (!isRed(x.left) && isRed(x.right))

                x = rotateLeft(x);

            if (isRed(x.left) && isRed(x.left.left))

                x = rotateRight(x);

            if (isRed(x.left ) && isRed(x.right))

                flipColors(x);

        }

        return x;

    }

    public static void main(String[] args) throws Exception {

        Scanner input = new Scanner(new File("data_BST.txt"));

        RedBlackTree bst = new RedBlackTree();

        while (input.hasNext()) {

            String key = input.next();

            int value = input.nextInt();

            bst.put(key, value);

        }

        System.out.println(bst.get("H"));

        System.out.println(bst.get("B"));

    }

}

```

你可能感兴趣的:(红黑树)