Left-leaning red-black BSTs (Guibas-Sedgewick 1979 and Sedgewick 2007)
1. Represent 2–3 tree as a BST.
2. Use "internal" left-leaning links as "glue" for 3–nodes
An equivalent definition
A BST such that:
1-1 correspondence with 2-3 trees
Key property. 1–1 correspondence between 2–3 and LLRB.
Observation. Search is the same as for elementary BST (ignore color).
Red-black BST representation
Each node is pointed to by precisely one link (from its parent) which can be encoded with color of BLACK or RED:
Elementary red-black BST operations
Left rotation. Orient a (temporarily) right-leaning red link to lean left.
Right rotation. Orient a left-leaning red link to (temporarily) lean right.
Color flip. Recolor to split a (temporary) 4-node.
Invariants. Maintains symmetric order and perfect black balance.
Insertion in a LLRB tree: overview
Basic strategy. Maintain 1-1 correspondence with 2-3 trees by applying elementary red-black BST operations.
Warmup 1. Insert into a tree with exactly 1 node.
Case 1. Insert into a 2-node at the bottom.
Warmup 2. Insert into a tree with exactly 2 nodes.
Case 2. Insert into a 3-node at the bottom.
Java implementation
Same code for all cases.
The complete sample code in Groovy:
- RedBlackBST.groovy
- package ds
- class RedBlackBST
extends Comparable ,V> { - private static boolean RED=true
- private static boolean BLACK=false
- private Node
root= null - private class Node
{ - K key
- V value
- Node
left=null - Node
right=null - Boolean color=false
- @Override
- public String toString()
- {
- return String.format("(%s,%s,%s)|%s|%s", key, value, color, left, right)
- }
- public void b(){color=false}
- public void r(){color=true}
- }
- private boolean isRed(Node n){
- if(n==null) return false
- else return n.color
- }
- public void put(K key, V value)
- {
- root=put(root, key, value)
- root.color=false
- }
- public Node put(Node h, K key, V value)
- {
- if(h == null) return new Node(key:key, value:value,color:true)
- int cmp = key.compareTo(h.key)
- if(cmp < 0) h.left = put(h.left, key, value)
- else if(cmp > 0) h.right = put(h.right, key, value)
- else h.value = value
- if(isRed(h.right) && !isRed(h.left)) h = rotateLeft(h)
- if(isRed(h.left) && isRed(h.left.left)) h = rotateRight(h)
- if(isRed(h.left) && isRed(h.right)) flipColors(h)
- return h
- }
- public V get(K k)
- {
- Node
node = root - while(node!=null)
- {
- int c = k.compareTo(node.key)
- if(c==0) return node.value
- else if(c<0) node = node.left
- else node = node.right
- }
- return null
- }
- private Node rotateLeft(Node h)
- {
- assert(isRed(h.right))
- Node x = h.right
- h.right = x.left
- x.left = h
- x.color = h.color
- h.r()
- return x
- }
- private Node rotateRight(Node h)
- {
- assert(isRed(h.left))
- Node x = h.left
- h.left = x.right
- x.right = h
- x.color = h.color
- h.r()
- return x
- }
- private Node flipColors(Node h)
- {
- assert(!isRed(h))
- assert(isRed(h.left))
- assert(isRed(h.right))
- h.r()
- h.left.b()
- h.right.b()
- }
- }
- package lab
- import ds.RedBlackBST
- class W5_E1 {
- static void main(args)
- {
- RedBlackBST
rbBST = new RedBlackBST () - def data = [] as Set
- Random rdm = new Random()
- 100.times{
- def k = rdm.nextInt(100)
- data.add(k)
- rbBST.put(k, k)
- }
- printf("BST Size=%d...\n", data.size())
- data.each{ key->
- assert(key==rbBST.get(key))
- }
- printf("Pass!")
- }
- }
沒有留言:
張貼留言