The Dictionary ADT
The Dictionary ADT
3 4
1
Binary Search Pseudocode for Binary Search
Algorithm BinarySearch(S, k, low, high)
• narrow down the search range in stages if low > high then
• “high-low” game return NO_SUCH_KEY
else mid ← (low+high) / 2
• Example: findElement(7) if k = key(mid) then
return key(mid)
else if k < key(mid) then
return BinarySearch(S, k, low, mid-1)
0 1 3 4 5 7 8 9 11 14 16 18 19 else return BinarySearch(S, k, mid+1, high)
l m h
2 4 5 7 8 9 12 14 17 19 22 25 27 28 33 37
0 1 3 4 5 7 8 9 11 14 16 18 19
l m h low mid high
0 1 3 4 5 7 8 9 11 14 16 18 19 2 4 5 7 8 9 12 14 17 19 22 27 28 33 37
25
l m h
0 1 3 4 5 7 8 9 11 14 16 18 19 low mid high
l=m =h 5
2 4 5 7 8 9 12 14 17 19 22 25 27 28 33 37
6
low mid
• The range of candidate items to be searched is halved • binary search runs in O(log n) time for findElement(k)
after each comparison • If we need to find all elements with a given key
(findAllElements(k)), it runs in O(log n + s), where s is the
number of element of elements in the iterator returned.
– Simply do a binary search to find an element equal to k. Then step back through
the array until you reach the first element equal to k. Finally, step forward through
the area adding each element to the iterator until you reach the first element that
is not equal to k. This takes O(logn) time for the search and then at most s time to
search back to the beginning of the run of k’s and s time return all of the elements
k. Therefore we have a solution running in at most O(logn+s) time.
2
Binary Search Tree
New Insertion Sort
1 4 = 8
9 10
Bob Frank
11 12
3
Operations
10
3 17
Searching: findElement(k):
1 8 15 20
13 14
4
Search Example I Search Example II
Algorithm findAllElements(k, v, c):
Input: The search key k, a node of the binary search tree v Unsuccessful findElement(25)
and a container c
Output: An iterator containing the found elements 25<44
if v is an external node then 25>17
return c.elements()
if k = key(v) then 25<32
c.addElement(v)
return findAllElements(k,T.rightChild(v), c) 25<28
else if k < key(v) then
return findAllElements(k,T,leftChild(v))
else leaf
{we know k > key(v)} node
return findAllElements(k,T,rightChild(v))
• An unsuccessful search traverses a path starting at the
Note that after finding k, if it occurs again, it will be in the left most root and ending at an external node
internal node of the right subtree.
17 18
5
Cost of Search: Best Case Cost of Search: Best Case
1 1 1 1 1 1
2 3 2 3 2 3 2 3 2 3 2 3
4 5 6 7 4 5 4 5 6 7 4 5 6 7 4 5 4 5 6 7
8 9 8 9
Σ ⎣log i⎦+1 =
1 2E 2(I + 2n)
2 O(log n) = = O(log n) FAILED
n 21 n+1 n+1 22
i=1
Insertion I expandExternal(v):
• To perform insertItem(k, e), let w be the node returned by
TreeSearch(k, T.root()) Transform v from an external node into an internal node
by creating two new children
• If w is external, we know that k is not stored in T. We call
expandExternal(w) on T and store (k, e) in w B B
A D A D
C E C E
new1 new2
expandExternal(v):
new1 and new 2 are the new nodes
if isExternal(v)
v.left ← new1
v.right ← new2
23 size ← size +2 24
6
Insertion II
• If w is internal, we know another item with key k is stored at w. We call
the algorithm recursively starting at T.rightChild(w) or T.leftChild(w) Construct a Tree
• They idea is to store the new item in an external node which either
precedes or follows the items with the same key in an inorder traversal.
What would be the result of constructing a
tree from repeated insertions of the
following sequences?
a. 5,8,3,7,1,9,2,4,6
b. 1,2,3,4,5,6,7,8,9
c. 5,4,6,3,7,2,8,1,9
When do you think trees work best?
25 26
Deletion
Construct a Tree 2 10
No children: simply
remove
5 15
27 28
7
Deletion I removeAboveExternal(v):
B
B
6 A D
• To perform operation < A D
removeElement(k), we 2 9
search for key k > C E
C
1 4 v 8
• Assume key k is in the
w G
tree, and let v be the node 5
F G
storing k
• If node v has a leaf child
w, we remove v and w from
the tree with operation 6 B
removeAboveExternal(w)
2 9 A D
• Example: remove 4
1 5 8
C
G
29 30
B B
A D
A D
C E C
F G
G
removeAboveExternal(v):
if isExternal(v)
{ p ← parent(v)
s ← sibling(v)
B if isRoot(v) s.parent ← null and root ← s
else
A G
v { g ← parent(p)
if (p is leftChild(g) g.left ← s
else g.right ← s
s.parent ← g
}
size ← size - 2 }
31 32
8
Deletion II
9
Performance of a dictionary
implementation with a binary search Conclusion
tree
Tree T with height h for n key-element items • To achieve good running time,
we need to keep the tree balanced,
• uses O(n) space
i.e., with O(logn) height.
• size, isEmpty : O(1)
• findElement, insertItem,
removeElement : O(h) • Various balancing schemes will be
explored next.
• findAllElements, removeAllElements :
O(h + s)
– s = size of the iterators returned
37 38
10