以特定的顺序(如降序)向基本的二叉搜索树中插入键值对时,可以导致二叉树的极度不平衡。在最坏情况下二叉树将退化为一条近似的链表,其时间复杂度在最坏情况下为O(n)。
为了保证在最坏情况下的性能,可以采用2-3树。与2-3树一一对应的便是红黑树。在红黑树中的结点Node中,具有一个属性color,表示指向这个结点的链接的颜色。规定:指向null结点的链接为黑色。
下面是红黑树的一个简单put和get的实现:
public class RedBlackTree<Key extends Comparable<Key>, Value> {
private static final boolean RED = true;
private static final boolean BLACK = false;
private Node root;
private class Node {
Key key;
Value val;
Node left;
Node right;
int n;
boolean color;
public Node(Key key, Value val, int n, boolean color) {
this.key = key;
this.val = val;
this.n = n;
this.color = color;
}
}
public boolean isRed(Node n) {
if(n == null)
return false;
return n.color == RED;
}
public int size(Node node) {
if(node == null)
return 0;
return node.n;
}
public Node rotateLeft(Node h) {
Node x = h.right;
h.right = x.left;
x.left = h;
x.color = h.color;
h.color = RED;
x.n = h.n;
h.n = 1 + size(h.left) + size(h.right);
return x;
}
public Node rotateRight(Node h) {
Node x = h.left;
h.left = x.right;
x.right = h;
x.color = h.color;
h.color = RED;
x.n = h.n;
h.n = 1 + size(h.left) + size(h.right);
return x;
}
public void flipColors(Node h) {
h.color = RED;
h.left.color = BLACK;
h.right.color = BLACK;
}
public void put(Key key, Value val) {
root = put(root, key, val);
root.color = BLACK;
}
private Node put(Node node, Key key, Value val) {
if(node == null)
return new Node(key, val, 1, RED);
int cmp = key.compareTo(node.key);
if(cmp < 0)
node.left = put(node.left, key, val);
else if(cmp > 0)
node.right = put(node.right, key, val);
else
node.val = val;
if(isRed(node.right) && !isRed(node.left))
rotateLeft(node);
if(isRed(node.left) && isRed(node.left.left))
rotateRight(node);
if(isRed(node.right) && isRed(node.left))
flipColors(node);
node.n = 1 + size(node.left) + size(node.right);
return node;
}
public Value get(Key key) {
Node node = get(root, key);
if(node == null)
return null;
return node.val;
}
private Node get(Node node, Key key) {
if(node == null)
return null;
int cmp = key.compareTo(node.key);
if(cmp == 0)
return node;
else if(cmp < 0)
return get(node.left, key);
else
return get(node.right, key);
}
}
向一颗红黑树中插入一对键值对时,通过递归调用,最终总是在树底的结点中插入。
与二叉树不同的地方只是在于,插入一个结点后,要进行一定的判断并对树的结构进行局部调整以保证树的(黑链接的)完美平衡性。
红黑树的时间复杂度为O(logn),Java中的TreeMap便是基于红黑树实现的。