Post on 13-Nov-2014
transcript
NUCES-FAST • Advanced Data Structures • Spring 2007
Height-biased Leftist Heaps
Rabea Aden
Friday, 1st May, 2007
For any node X Є Leftist Tree, Rightmost path is the Shortest
Leftist Tree
• Invented by Clark Allan Crane
• A Leftist Tree is a priority queue
• It satisfies the leftist structural property
Null Path Length
• denoted by npl(X)• Length of shortest path from X to an external
node
npl(NULL) = -1
If X has zero or one child, npl(X) = 0
Otherwise
hild(X))}npl(rightC ild(X)),npl(leftCh { min 1 npl(X)
Null Path Length
if X has zero or one childnpl(X) = 0
else npl(X) = 1 + min{ npl( leftChild(X) ), npl( rightChild(X) ) }
0
0 0
1
0
0
0
1
npl(NULL) = -1
-1 -1
-1 -1 -1
-1 -1
-1
-1
Null
Null
Null
NullNullNull
Null Null Null
Structural Property
• Height-biased Leftist Property
• Tree is unbalanced • Biased towards left• Left paths are long, giving the name Leftist Tree• Rightmost path is the shortest
hild(X))npl(rightC ild(X))npl(leftCh HBLT X
Structural Property
Null path lengths: T1 is a Height-biased Leftist Tree, T2 is not
T1 T2
Leftist Heap Property Violatednpl(leftChild) < npl(rightChild)
0
0 0 0 0
1 1
2
0
0 0 0 1
1 1*
2
Leftist Heap
• A Heap-ordered Leftist Tree
Heap-order Property
• Min Leftist Heap
• Max Leftist Heap
(X))key(Parent key(X) Heap X
(X))key(Parent key(X) Heap X
If X is root Parent (X) = root
Binary Heap vs. Leftist Heap
Binary Heap Leftist Heap — Perfectly balanced — Very unbalanced
Operations Binary Heap Leftist Heap
BuildHeapFindMinMergeInsertDeleteMin
O(N)O(1)Θ(N)
O(log N)O(log N)
O(N)O(1)
O(log N)O(log N)O(log N)
Binary Heap Leftist Heap — Perfectly balanced — Very unbalanced
Merge is expensive in ordinary Heaps
Operations Binary Heap Leftist Heap
BuildHeapFindMinMergeInsertDeleteMin
O(N)O(1)Θ(N)
O(log N)O(log N)
O(N)O(1)
O(log N)O(log N)O(log N)
Binary Heap vs. Leftist Heap
Theorem
The number of nodes N in a leftist tree
with r nodes on the right path is ≥ 2r -1
Proof is by Induction
This gives
1)(nlogr12N 2r
Structure of a Node
DataLeft
PointerRight
PointerNPL
Apart from data, left and right pointers, each node also contains the null path length
Design
• A Leftist Tree is a priority queue implemented using a variant of the Binary Tree
• A pointer to the root of the leftist tree is also maintained
Extended Binary Tree
Extended Binary Tree
Given: A Binary Tree TB
For all empty subtrees є TB
replace each empty subtree with an external node
Binary Tree
Replace each empty subtree with an external node
Internal Node
Extended Binary Tree
Replace each empty subtree with an external nodeThe number outside each node X is the npl(X)
External Node
Since an External Node represents NULLnpl(External Node) = -1
-1 -1 -1 -1
-1 -1 -1
-1
0 -1 0
00 0
01
1
Internal Node
Operations
• BuildHeap O(N)
• FindMin O(1)
• Merge O(log N)
• Insert O(log N)
• DeleteMin O(log N)
General Idea
• All insertions and merges are performed on the rightmost path containing at most nodes
• This may violate Leftist Heap Property• Leftist Heap Property can be easily restored
1)(nlog2
Merge
• O(log N) time
• It is a fundamental operation– Both Insert and DeleteMin are based on Merge– Insert:
• The key to be inserted is a one-node heap• Merge this one-node heap with the given min leftist heap
– DeleteMin• Delete root, left and right child of root are two min leftist heaps• Merge the two min leftist heaps
Merge Algorithm (Recursive)Merge(H1, H2)
If both heaps are Leftist
If one heap is NULL then return the other
If data(H1) > data(H1) then swap H1 and H2
If leftChild(H1) is NULL then leftChild(H1) = H2
Otherwise,
Recursively Merge rightChild(H1) and H2
If Leftist Heap Property is violated i.eIf npl( leftChild(H1) ) < npl( rightChild(H1) ) then swap children of H1
npl(H1) = npl(rightChild(H1)) + 1
130
170
370
91
22
61
70
410
H1
Merge H1 & H2
Both H1 and H2 are Min Leftist Heaps
32
150
51
110
290
260
230
190
81
H2
32
150
51
110
290
260
230
190
81
H2
32
150
51
110
290
260
230
190
81
H2
130
170
370
91
22
61
70
410
H1
Merge (H1, H2)
Compare root(H1) '2' & root(H2) '3' — H1 has smaller root
130
170
370
91
22
61
70
410
H1
Both H1 and H2 are not NULL
Merge H1 & H2
130
170
370
91
22
61
70
410
130
170
370
91
22
61
70
410
H1
32
150
51
110
290
260
230
190
81
H2
Since, leftChild(H1) ≠ NULL H1 now points to its rightChild
H1
Merge H1 & H2
Merge H1 & H2
Merge (H1, H2)
Compare root(H1) '9' & root(H2) '3' — H2 has smaller root swap(H1, H2)
Now, root(H1) = '3' & root(H2) = '9'
32
150
51
110
290
260
230
190
81
H1
170
370
91
410
130
22
61
70
Both H1 and H2 are not NULL
H2
Merge H1 & H2
Resizing H1
H2
170
370
91
410
130
22
61
70
32
150
51
110
290
260
230
190
81
H1
32
150
51
110
290
260
230
190
81
130
2
22
61
70
3
150
51
110
290
260
230
190
81
Merge H1 & H2
Since, leftChild(H1) ≠ NULL H1 now points to its rightChild
H2
170
370
91
410
130
22
61
70
130
2
22
61
70
3
150
51
110
290
260
230
190
81
H1
130
2
22
61
70
3
150
51
110
290
260
230
190
81
Merge H1 & H2
Merge (H1, H2)
Compare root(H1) '8' & root(H2) '9' — H1 has smaller root
H2
170
370
91
410
Both H1 and H2 are not NULL
H1
130
2
22
61
70
3
150
51
110
290
260
230
190
81
130
2
22
61
70
3
150
51
110
290
260
230
190
81
Merge H1 & H2
Since, leftChild(H1) ≠ NULL H1 now points to its rightChild
H2
170
370
91
410
H1
Merge H1 & H2
Merge (H1, H2)
Compare root(H1) '23' & root(H2) '9' — H2 has smaller root swap(H1, H2)
Now, root(H1) = '9' & root(H2) = '23'
1737941
Both H1 and H2 are not NULL
260
230
130
2
22
61
70
3
150
51
110
290
190
81
H2
170
370
91
410
H1
Merge H1 & H2
Resizing H1
1737941
H2
260
230
130
2
22
61
70
3
150
51
110
190
81
170
370
91
410
290
290
H1
130
2
22
61
70
3
150
51
110
190
81
170
370
91
410
290
Merge H1 & H2
1737941
H2
260
230
Since, leftChild(H1) ≠ NULL H1 now points to its rightChild
130
2
22
61
70
3
150
51
110
190
81
170
370
91
410
290
H1
Merge H1 & H2
1737941
H2
260
230
Merge (H1, H2)
Compare root(H1) '37' & root(H2) '23' — H2 has smaller root swap(H1, H2)
Now, root(H1) = '23' & root(H2) = '37'
Both H1 and H2 are not NULL
130
2
22
61
70
3
150
51
110
190
81
170
91
290
370
410
H1
Merge H1 & H2
Since, leftChild(H1) ≠ NULL H1 now points to its rightChild — NULL
1737941
H2
410
370
130
2
22
61
70
3
150
51
110
290
190
81
170
230
91
260
NULL
H1
130
2
22
61
70
3
150
51
110
290
190
81
170
230
91
260
Merge H1 & H2
NULL
H1 is NULL
130
2
22
61
70
3
150
51
110
190
81
170
230
91
260
290
410
370
H1
H2
Merge (H1, H2)
Since root(H1) is 'NULL' swap(H1, H2)
Now, root(H1) = '37' & root(H2) = 'NULL'
Merge H1 & H2
130
2
22
61
70
3
150
51
110
190
81
170
230
91
260
290
370
410
NULL
H2
H2 is NULL
Adjust Null Path Lengths from the Last Node
on the Rightmost Path to the Root
H1
NULL
Merge H1 & H2
Adjust Null Path Lengths from the Last Node
on the Rightmost Pathto the Root
130
2
22
61
70
3
150
51
110
190
81
170
230
91
260
290
370
410
H1
NULL
130
2
22
61
70
3
150
51
110
190
81
170
230
91
260
290
370
410
leftChild(H1)→npl ≥ rightChild(H1)→npl — 0 ≥ -1H1→npl = rightChild(H1)→npl + 1 = '0'
npl (NULL) = -1
H1 points to '37'
Leftist Heap Property NOT Violated
Merge H1 & H2
H1
NULL
130
2
22
61
70
3
150
51
110
190
81
170
230
91
260
290
370
410
H1 moves up to '23'
leftChild(H1)→npl ≥ rightChild(H1)→npl — 0 ≥ 0H1→npl = rightChild(H1)→npl + 1 = '1'
130
2
22
61
70
3
150
51
110
190
81
170
23
91
260
290
370
410
10*
npl (NULL) = -1
Leftist Heap Property NOT Violated
Merge H1 & H2
leftChild(H1)→npl ≥ rightChild(H1)→npl — 0 ≤ 1
130
2
22
61
70
3
150
51
110
190
81
170
23
91
260
290
370
410
H1
1
H1 moves up to '9'
Leftist Heap Property Violatedswap( leftChild(H1), rightChild(H1) )
130
2
22
61
70
3
150
51
110
190
81
170
23
9
260
290
370
410
1
1*
Merge H1 & H2
leftChild(H1)→npl ≥ rightChild(H1)→npl — 0 ≤ 1H1→npl = rightChild(H1)→npl + 1 = '1'
H1 moves up to '9'
Leftist Heap Property Violatedswap( leftChild(H1), rightChild(H1) )
1*1130
2
22
61
70
3
150
51
110
190
81
9
290
23
260
370
410
1
H1
170
Merge H1 & H2
leftChild(H1)→npl ≥ rightChild(H1)→npl — 0 ≤ 1H1→npl = rightChild(H1)→npl + 1 = '1'
1
H1
H1 moves up to '8'
1*1
Leftist Heap Property Violatedswap( leftChild(H1), rightChild(H1) )
130
2
22
61
70
3
150
51
110
8
190
290
231
17
9
260
370
410
0
1
190
290
130
2
22
61
70
3
150
51
110
190
81
231
17
9
260
290
370
410
0
Merge H1 & H2
leftChild(H1)→npl ≥ rightChild(H1)→npl — 1 ≥ 1H1→npl = rightChild(H1)→npl + 1 = '2'
H1 moves up to '3'130
2
22
61
70
3
150
51
110
190
81
0
23
9
260
290
370
410
1
17
1
H1
1130
2
22
61
70
3
150
51
110
190
81
0
23
9
260
290
370
410
1
17
0
Leftist Heap Property NOT Violated
Merge H1 & H2
leftChild(H1)→npl ≥ rightChild(H1)→npl — 1 ≤ 2H1→npl = rightChild(H1)→npl + 1 = '2'
2*2
130
2
22
61
70
3
150
51
110
190
81
0
23
9
260
290
370
410
1
17
0H1 moves up to '2'
2
2
3
150
51
110
190
81
0
23
9
260
290
370
410
1
17
0
130
61
70
Leftist Heap Property Violatedswap( leftChild(H1), rightChild(H1) )
H1
Merge H1 & H2
H1 is returned Root pointer now points to H1
H1
130
1
2
32
70
6
150
51
110
190
81
0
23
9
260
290
370
410
1
17
0
2
130
1
2
32
70
6
150
51
110
190
81
0
23
9
260
290
370
410
1
17
0
2
Root
Merge Algorithm (Iterative)
Merge(H1, H2)
Pass 1 — Down the HeapSort nodes on rightmost paths of H1 and H2 in ascending order (leftChild of each node remains)A new tree H is created by merging the sorted nodes
Pass 2 — Up the Heap nodes X Є rightmost path of H from leaf to the root
If Leftist Heap Property is violated i.eIf npl( leftChild(X) ) < npl( rightChild(X) ) then swap children of X
npl(X) = npl(rightChild(X) + 1
Time Complexity of Merge
• O(log n)
• As only shortest path is traversed
Insert
• O(log N) time
Insert is based on Merge
Existing min leftist heap — H1 The key to be inserted is a one-node heap — H2 Merge this one-node heap H1 with the given min
leftist heap H2
Insert 3
H1 — existing HeapH2 — one-node heap containing node to be inserted
Both H1 and H2 are Min Leftist Heaps
130
170
370
91
22
61
70
410
H1
30
H2
Insert 3
130
170
370
91
22
61
70
410
H1
30
H2
130
170
370
91
22
61
70
410
H1
30
H2
Both H1 and H2 are not NULL
Merge (H1, H2)
Compare root(H1) '2' & root(H2) '3' — H1 has smaller root
Insert 3
130
170
370
91
22
61
70
410
Since, leftChild(H1) ≠ NULL H1 now points to its rightChild
H1
H1 30
H2
Insert 3
H1
130
22
61
70
Merge (H1, H2)
Compare root(H1) '9' & root(H2) '3' — H2 has smaller root swap(H1, H2)
Now, root(H1) = '3' & root(H2) = '9'
Both H1 and H2 are not NULL30
H2
170
370
91
410
NULL
Insert 3
H1
30
Since, leftChild(H1) == NULL leftChild(H1) = H2
170
370
91
410
130
22
61
70
H2
130
30
22
61
70
170
370
91
410
Insert 3
H1
H2
130
30
22
61
70
170
370
91
410
NULL
H2 is NULLAdjust Null Path Lengths
from the last node on the Rightmost Path
to the Root
Insert 3
H1
leftChild(H1)→npl ≥ rightChild(H1)→npl — 1 ≥ -1H1→npl = rightChild(H1)→npl + 1 = '0'
npl (NULL) = -1130
30
22
61
70
170
370
91
410
NULL
Adjust Null Path Lengths from the last node
on the Rightmost Path to the Root
H1 points to '3'
Leftist Heap Property NOT Violated
130
30
22
61
70
170
370
91
410
Insert 3
H1
leftChild(H1)→npl ≥ rightChild(H1)→npl — 1 ≥ 0H1→npl = rightChild(H1)→npl + 1 = '1'
npl (NULL) = -1130
30
22
61
70
170
370
91
410
Leftist Heap Property NOT Violated
12*
NULL
H1 moves up to '2'
130
30
2
61
70
170
370
91
410
Insert 3
H1 is returned Root pointer now points to H1
H1
1
130
30
2
61
70
170
370
91
410
130
30
2
61
70
170
370
91
410
1
Root
Time Complexity of Insert
• O(log n)
• Create a one-node heap — O(1)• Merge — O(log n)
– As only shortest path is traversed
DeleteMin
• O(log N) time
DeleteMin is based on Merge
Delete root — (minimum value is in root) Left and right children of root are two min
leftist heaps — H1 and H2 respectively Merge the two min leftist heaps H1 and H2
DeleteMin
130
170
370
91
22
61
70
410
Root
Delete Minimum Key '2'
130
170
370
91
22
61
70
410
DeleteMin
Save old value of rootH1 = root→leftChildH2 = root→rightChild
130
61
70
170
370
91
410
H1 H2
RootoldRoot
22
22
DeleteMin
130
61
70
170
370
91
410
H1 H2
Merge (H1, H2)
Compare root(H1) '6' & root(H2) '9' — H1 has smaller root
Both H1 and H2 are not NULL
oldRoot
130
61
70
170
370
91
410
22
DeleteMin
H1 H2
oldRoot
22
Since, leftChild(H1) ≠ NULL H1 now points to its rightChild
H1
170
370
91
410
130
61
70
130
61
70
DeleteMin
H2
oldRoot
22
H1
170
370
91
410
Both H1 and H2 are not NULL61
70
130
Merge (H1, H2)
Compare root(H1) '9' & root(H2) '3' — H2 has smaller root swap(H1, H2)
Now, root(H1) = '3' & root(H2) = '9'
DeleteMin
H2
oldRoot
22
H1
170
370
91
61
70
410
130
Since, leftChild(H1) ≠ NULL H1 now points to its rightChild
170
370
91
61
70
410
DeleteMin
H2
oldRoot
22
130
H1
Merge (H1, H2)
Compare root(H1) '37' & root(H2) '13' — H2 has smaller root swap(H1, H2)
Now, root(H1) = '37' & root(H2) = '13'
170
91
61
70
370
410
Both H1 and H2 are not NULL
DeleteMin
H2
oldRoot
22
H1
170
91
61
70
Since, leftChild(H1) == NULL leftChild(H1) = H2
NULL
130
370
410
170
130
91
61
70
370
410
DeleteMin
H2
oldRoot
22
H1
NULL
170
130
91
61
70
370
410
H2 is NULL
Adjust Null Path Lengths from the last node
on the Rightmost Path to the Root
DeleteMinoldRoot
22
170
130
91
61
70
370
410
H1
leftChild(H1)→npl ≥ rightChild(H1)→npl — 0 ≥ -1H1→npl = rightChild(H1)→npl + 1 = '0'
npl (NULL) = -1
Adjust Null Path Lengths from the last node
on the Rightmost Path to the Root
H1 points to '13'
Leftist Heap Property NOT Violated
NULL
170
130
91
61
70
370
410
170
130
91
61
70
370
410
DeleteMinoldRoot
22
H1
leftChild(H1)→npl ≥ rightChild(H1)→npl — 0 ≥ 0H1→npl = rightChild(H1)→npl + 1 = '1'
npl (NULL) = -1
H1 moves up to '9'
Leftist Heap Property NOT Violated
NULL
170
130
91
61
70
370
410
DeleteMinoldRoot
22
leftChild(H1)→npl ≥ rightChild(H1)→npl — 0 ≤ 1H1→npl = rightChild(H1)→npl + 1 = '1'
H1 moves up to '6'
Leftist Heap Property Violatedswap( leftChild(H1), rightChild(H1) )
170
130
91
61
70
370
410
H1
H1
6
170
130
91
370
410
70
1*1
6
170
130
91
370
410
70
DeleteMinoldRoot
22
H1
1
H1 is returned Root pointer now points to H1
Delete old value of Root
Root
61
170
130
91
370
410
70
Time Complexity of DeleteMin
• O(log n)
• Delete root — O(1)• Initialize H1 with left child of root — O(1)• Initialize H2 with right child of root — O(1)• Merge — O(log n)
– As only shortest path is traversed
Brute Force BuildHeap
• O(N logN) time
Based on Insert
Given N elements, create N one-node min leftist heaps and insert them into a Queue, Q
Size of Q, |Q| = N
Root = Remove first min leftist heap from queue
while( |Q| > 0 )Remove one min leftist heaps from queue — HInsert( H )
Brute Force BuildHeap
70
90
370
20
60
130
Build a min leftist heap containing elements7, 9, 37, 41, 2, 6, 13
Create 7 one-node min leftist heaps and insert them in a queue — |Q| = 7
410
70
Brute Force BuildHeap
70
70
90
90
370
20
60
130
Root = 7 |Q| = 6H = 9 |Q| = 5Insert( H )
410
70
90
90
Root H
Brute Force BuildHeap
370
20
60
130
Root = 7 |Q| = 5H = 37 |Q| = 4Insert( H )
410
70
90
Root H
70
90
370
370
71
90
370
71
90
Brute Force BuildHeap
20
60
130
Root = 7 |Q| = 4H = 41 |Q| = 3Insert( H )
410
Root H
370
71
90
370
71
90
410
370
71
90
410
370
71
90
410
Brute Force BuildHeap
20
60
130
Root = 7 |Q| = 3H = 2 |Q| = 2Insert( H )
Root H
370
71
90
410
370
71
90
410
20
20
370
71
90
410
20
370
71
90
410
Brute Force BuildHeap
130
Root = 7 |Q| = 2H = 6 |Q| = 1Insert( H )
Root H
20
370
71
90
410
20
370
71
90
410
60
60
21
370
71
90
410
60
21
370
71
90
410
60
Brute Force BuildHeap
130
Root = 7 |Q| = 1H = 13 |Q| = 0Insert( H )
Root H
21
370
71
90
410
60
130
21
370
71
90
410
60
130
21
370
71
90
410
60
21
370
71
90
410
60
130
Time Complexity of Brute Force BuildHeap
• O(N log N)
1 insert — O(log N)
N inserts — O(N log N)
Efficient BuildHeap
• O(N) time
Based on Merge
Given N elements, create N one-node min leftist heaps and insert them into a Queue, Q
Size of Q, |Q| = N
while( |Q| > 1 )Remove first two min leftist heaps from queue — H1 and H2Merge H1 and H2 Insert merged min leftist heap into queue
Efficient BuildHeap
70
90
370
20
60
130
Build a min leftist heap containing elements7, 9, 37, 41, 2, 6, 13
Create 7 one-node min leftist heaps and insert them in a queue — |Q| = 7
410
70
Efficient BuildHeap
70
70
90
90
370
20
60
130
Remove and merge first two min leftist heaps from queue H1 = 7 |Q| = 6H2 = 9 |Q| = 5H1 = Merge(H1, H2)
Insert H1 into queue |Q| = 6
410
90
H1
70
90
H2
Efficient BuildHeap
70
90
370
20
60
130
Remove and merge first two min leftist heaps from queue H1 = 37 |Q| = 5H2 = 41 |Q| = 4H1 = Merge(H1, H2)
Insert H1 into queue |Q| = 5
H1
410
370
410
370
410
H2
370
410
Efficient BuildHeap
70
90
20
60
130
Remove and merge first two min leftist heaps from queue H1 = 2 |Q| = 4H2 = 6 |Q| = 3H1 = Merge(H1, H2)
Insert H1 into queue |Q| = 4
H1 H2
370
410
20
60
20
60
20
60
Efficient BuildHeap
130
Remove and merge first two min leftist heaps from queue H1 = 13 |Q| = 3H2 = 7 |Q| = 2H1 = Merge(H1, H2)
Insert H1 into queue |Q| = 3
H1 H2
370
410
20
60
130
71
90
70
90
130
70
90
130
71
90
Efficient BuildHeap
Remove and merge first two min leftist heaps from queue H1 = 37 |Q| = 2H2 = 2 |Q| = 1H1 = Merge(H1, H2)
Insert H1 into queue |Q| = 2
H1 H2
370
410
20
60
130
71
90
20
60
370
410
370
21
60
410
370
21
60
410
Efficient BuildHeap
130
71
90
130
71
90
Remove and merge first two min leftist heaps from queue H1 = 7 |Q| = 1H2 = 2 |Q| = 0H1 = Merge(H1, H2)
Insert H1 into queue |Q| = 1
H1 H2
370
21
60
410
130
60
21
71
90
370
410
370
21
60
410
130
60
21
71
90
370
410
Efficient BuildHeap
Since |Q| > 0Root = 2
130
60
21
71
90
370
410
Root
Time Complexity of Efficient BuildHeap
Assume min leftist heap contains N = 2k elements
Merge Operations Recursive Calls to Merge
N/2 1
N/4 2
N/8 3
׃
׃
N/2k = 1 k
Time Complexity of Efficient BuildHeap
Total Time for BuildHeap
)N(
3nforn3
2i
N
2i
N
)21
81
41
21(N
)k*2N
()3*8N
()2*4N
()1*2N
(
1ii
k
1ii
k
k