目录
  1. 1. 红黑树
  2. 2. 1 概念介绍
    1. 2.0.1. 2 代码实现
红黑树

红黑树

1 概念介绍

  • 算法导论给出的定义

1.每个节点或者是红色的,或者是黑色的
2.根节点是黑色的
3.每一个叶子节点(最后的空节点)是黑色的
4.如果一个节点是红色的,那么他的孩子节点都是黑色的(因为红色节点只能是黑色节点的左子节点,这也表明黑色节点右子树连接节点也是黑色的)
5.从任意一个节点到叶子节点,经过的黑色节点是一样的(因为和二三树等价,红色节点可以忽略。所以也说红黑树是黑平衡的二叉树,他的时间复杂度最差会退化成2logn)

  • 红黑树和二三树其实是等价的
    • 二三树是一种二分搜索树,但是不是二叉树
    • 二三树是一颗绝对平衡树,即从根节点到任意叶子节点所经过的节点数一定相同
  • 红黑树其实就是把二三树中三节点左侧的节点变为左子树,且变为红颜色
  • 红黑树新添加节点都是红色的,红色节点首先要看是否能和上游节点融合
  • 红黑树统计性能好,还有一种splay tree性能也好

image-20200228105900091

2 代码实现

下面的代码是左倾的红黑树,也可以使用右倾

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public class RBTree<K extends Comparable<K>,V> {
private static final boolean RED = true;
private static final boolean BLACK = false;
private class Node{
public K key;
public V value;
public Node left, right;
public boolean color;
public Node(K key,V value) {
this.key = key;
this.value = value;
left = null;
right = null;
color = RED;
}
}
private Node root;
private int size;
public RBTree(){
root = null;
size = 0;
}
public int getSize() { return size; }
public boolean isEmpty() { return size == 0; }

//判断节点颜色
private boolean isRed(Node node){
if(node == null){
return BLACK;
}
return node.color;
}
//向红黑树中添加新元素
public void add(K key, V value){
root = add(root,key,value);
root.color = BLACK;//根节点必须为黑色
}
//add私有方法实现,向以node为跟的红黑树插入新元素的递归算法
//返回根节点
private Node add(Node node,K key, V value){
if(node == null){
size++;
return new Node(key,value);
}
if(key.compareTo(node.key) < 0)
node.left = add(node.left, key, value);
else if (key.compareTo(node.key) > 0)
node.right = add(node.right, key, value);
else
node.value = value;
if(isRed(node.right) && !isRed(node.left))
leftRotate(node);
if(isRed(node.left) && isRed (node.left.left))
node = rightRotate(node) ;
if(isRed(node.left) && isRed(node. right))
flipColors (node);
return node;

}
//二节点add方法中,当加入的新节点大于根节点时左旋转
//把 原来根节点 设置为 新的根节点的左节点
private Node leftRotate(Node node){
Node x = node.right;
node.right = x.left;//把原来x节点左侧的树挪到node上
x.left = node;
x.color = node.color;
node.color = RED;
//这里有一个问题,此时可能会有两个红节点连在一起,后续解决
return x;
}
//三节点时添加元素成为四节点,有以下三种情况
//在右侧,四节点情况时颜色翻转
private void flipColors(Node node){
node.color = RED;
node.left.color = BLACK;
node.right.color= BLACK;
}
//右旋转,本来就是三节点,又要在三节点左侧插入节点
private Node rightRotate(Node node){
Node x = node.left;
node.left = x.right;
x.right = node;
x.color = node.color;
node.color = RED;
return x;
}
//如果加入的数在中间,先进行一次左旋转变为上一钟情况
}
//删除节点这里不涉及,太难
文章作者: liuDH
文章链接: http://yoursite.com/2020/02/28/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E7%BA%A2%E9%BB%91%E6%A0%91/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 毛毛裤裤的世界
打赏
  • 微信
  • 支付寶