❖ Balancing Binary Search Trees |
Observation: order of insertion into a tree affects its height
❖ ... Balancing Binary Search Trees |
Perfectly-balanced tree with N nodes has
❖ Operations for Rebalancing |
To assist with rebalancing, we consider new operations:
Left rotation
❖ ... Tree Rotation |
Method for rotating tree T right:
Rotation requires simple, localised pointer rearrangemennts
Cost of tree rotation: O(1)
❖ ... Tree Rotation |
Algorithm for right rotation:
rotateRight(n1): | Input tree n1 | Output n1 rotated to the right | | if n1 is empty ∨ left(n1) is empty then | return n1 | end if | n2=left(n1) | left(n1)=right(n2) | right(n2)=n1 | return n2
❖ ... Tree Rotation |
Algorithm for left rotation:
rotateLeft(n2): | Input tree n2 | Output n2 rotated to the left | | if n2 is empty ∨ right(n2) is empty then | return n2 | end if | n1=right(n2) | right(n2)=left(n1) | left(n1)=n2 | return n1
❖ ... Tree Rotation |
Cost considerations for tree rotation
❖ Insertion at Root |
Previous discussion of BSTs did insertion at leaves.
Different approach: insert new item at root.
Potential disadvantages:
❖ ... Insertion at Root |
Method for inserting at root:
❖ ... Insertion at Root |
Algorithm for inserting at root:
insertAtRoot(t, it): | Input tree t, item it to be inserted | Output modified tree with item at root | | if t is empty tree then | t = new node containing item | else if item < root(t) then | left(t) = insertAtRoot(left(t), it) | t = rotateRight(t) | else if it > root(t) then | right(t) = insertAtRoot(right(t), it) | t = rotateLeft(t) | end if | return t;
❖ ... Insertion at Root |
Analysis of insertion-at-root:
❖ Tree Partitioning |
Tree partition operation partition(tree,i)
For tree with N nodes, indices are 0 .. N-1, in LNR order
❖ ... Tree Partitioning |
Implementation of partition operation:
partition(tree,i): | Input tree with n nodes, index i | Output tree with ith item moved to the root | | m=#nodes(left(tree)) | if i < m then | left(tree)=partition(left(tree),i) | tree=rotateRight(tree) | else if i > m then | right(tree)=partition(right(tree),i-m-1) | tree=rotateLeft(tree) | end if | return tree
Note: size(tree) = n, size(left(tree)) = m, size(right(tree)) = n-m-1
❖ ... Tree Partitioning |
Analysis of tree partitioning
❖ Periodic Rebalancing |
An approach to maintaining balance:
| Input tree, item | Output tree with item randomly inserted | | t=insertAtLeaf(tree,item) | if #nodes(t) mod k = 0 then | t=rebalance(t) | end if | return t
When to rebalance? e.g. after every k insertions
❖ ... Periodic Rebalancing |
A problem with this approach ...
typedef struct Node { int data; int nnodes; // #nodes in my tree Tree left, right; // subtrees } Node;
But maintaining nnodes requires extra work in other operations
❖ ... Periodic Rebalancing |
Implementation of rebalance:
rebalance(t): | Input tree t with n nodes | Output t rebalanced | | if n≥3 then | | // put node with median key at root | | t=partition(t,n/2) | | // then rebalance each subtree | | left(t)=rebalance(left(t)) | | right(t)=rebalance(right(t)) | end if | return t
❖ ... Periodic Rebalancing |
Analysis of rebalancing: visits every node ⇒ O(N)
Cost means not feasible to rebalance after each insertion.
When to rebalance? … Some possibilities:
Does it solve the problem? … Not completely ⇒ Solution: real balanced trees (next week)
❖ Randomised BST Insertion |
Reminder: order of insertion can dramatically affect shape of tree
Tree ADT has no control over order that keys are supplied.
We know that inserting in random order gives O(log2n) search
Can the algorithm itself introduce some randomness?
In the hope that this randomness helps to balance the tree …
❖ ... Randomised BST Insertion |
Approach: normally do leaf insert, randomly do root insert.
insertRandom(tree,item)
| Input tree, item
| Output tree with item randomly inserted
|
| if tree is empty then
| return new node containing item
| end if
| // p/q chance of doing root insert
| if random() mod q < p then
| return insertAtRoot(tree,item)
| else
| return insertAtLeaf(tree,item)
| end if
E.g. 30% chance ⇒ choose p=3, q=10
❖ ... Randomised BST Insertion |
Cost analysis:
❖ An Application of BSTs: Sets |
Trees provide efficient search.
Sets require efficient search
❖ ... An Application of BSTs: Sets |
Assuming we have BST implementation with type Tree
Set
SetInsert(Set,Item)
TreeInsert(Tree,Item)
SetDelete(Set,Item)
TreeDelete(Tree,Item.Key)
SetMember(Set,Item)
TreeSearch(Tree,Item.Key)
❖ ... An Application of BSTs: Sets |
Concrete representation:
#include <Tree.h> typedef struct SetRep { int nelems; Tree root; } SetRep; Set newSet() { Set S = malloc(sizeof(SetRep)); assert(S != NULL); S->nelems = 0; S->root = newTree(); return S; }
Produced: 8 Jun 2020