Binary Search Tree
Properties:
- Binary Tree
- key[leftSubtree(x)] ≤ key[x] ≤ key[rightSubtree(x)]
Traverse:
- Inorder: left, root, right;
(Keys are printed in sorted order)- Preorder: root, left, right
- Postorder: left, right, root
Operations:
- SEARCH, MINIMUM, MAXIMUM, PREDECESSOR, SUCCESSOR, INSERT, DELETE
- Best case: Θ(logn) = Θ(h); on average: Θ(logn) = Θ(h); worst case: Θ(n) (very unbalanced)
//Running Time: O (h), h – the height of the tree
TREE-SEARCH(x, k)
if x = NIL or k = key [x]
then return x
if k < key [x]
then return TREE-SEARCH(left [x], k )
else return TREE-SEARCH(right [x], k )
//Running time: O(h), h – height of tree
TREE-MINIMUM(x)
while left [x] != NIL
do x ← left [x]
return x
//Running time: O(h), h – height of tree
TREE-MAXIMUM(x)
while right [x] != NIL
do x ← right [x]
return x
//Def: successor (x) = y, such that key [y] is the smallest key > key [x]
//Running time: O (h), h – height of the tree
TREE-SUCCESSOR(x)
// Case 1: right (x) is non empty
if right [x] != NIL
then return TREE-MINIMUM(right [x])
// Case 2: right (x) is empty
y ← p[x] // p[x]: parent of x
while y != NIL and x = right [y]
do x ← y
y ← p[y]
return y
// Def: predecessor (x ) = y, such that key [y] is the biggest key < key [x]
TREE-PREDECESSOR(x)
// Case 1: left (x) is non empty
if left [x] != NIL
then return TREE-MAXIMUM(left [x])
// Case 2: left (x) is empty
y ← p[x] // p[x]: parent of x
while y != NIL and x = left [y]
do x ← y
y ← p[y]
return y
//Running time: O(h)
TREE-INSERTION(z)
y ← NIL // parent of x
x ← root [T]
while x != NIL
do y ← x
if key [z] < key [x]
then x ← left [x]
else x ← right [x]
p[z] ← y // p[z]: parent of z
if y = NIL // Tree T was empty
then root [T] ← z
else if key [z] < key [y]
then left [y] ← z
else right [y] ← z
TREE-DELETION(z)
// Case 1: z has no children
if left [x] = NIL and right [x] = NIL
then p[z] ← NIL
// Case 2: z has one child
else if left [x] != NIL
then p[z] ← left [x]
else if right [x] != NIL
then p[z] ← right [x]
// Case 3: z has two child
else
y ← SUCCESSOR(x) // y has either no children or one right child
DELETION(y)
z ← y
Balanced binary search trees
- AVL (Adelson-Velskii and Landis) trees
- B-trees
- Red-black tree
AVL Trees
Property:
- Balance factor of a node: height(left subtree) - height(right subtree)
- For every node, heights of left and right subtree can differ by no more than 1
Rotations: to restore the AVL tree property/balance
- If the AVL tree property is violated at a node x, the heights of left(x) and right(x) differ by exactly 2.
- single rotation or double rotations
Insertion
- step 1: insert the new key in BST
- step 2: check if heights of left(x) and right(x) differ by at most 1 from new leaf towards the root
If yes, proceed to parent(x).
If not, restructure by doing either a single rotation or a double rotation.- For insertion, once we perform a rotation at a node x, don’t need to perform any rotation at any ancestor of x.
Let U be the node nearest to the inserted one which has an imbalance.
- Single rotation:
Insertion in the left subtree of the left child of U
Insertion in the right subtree of the right child of U
- Double rotation:
Insertion in the right subtree of the left child of U
Insertion in the left subtree of the right child of U
Running Times for AVL Trees
- A single restructure/rotation is O(1)
- Find/search is O(log n)
height of tree is O(log n), no restructures needed- Insertion(Deletion) is O(log n)
initial find is O(log n)
Restructuring up the tree, maintaining heights is O(log n)