# height-biased leftist heaps advanced)

Click here to load reader

Post on 13-Nov-2014

113 views

Embed Size (px)

TRANSCRIPT

Height-biased Leftist HeapsRabea Aden Friday, 1st May, 2007

NUCES-FAST Advanced Data Structures Spring 2007

Leftist Tree Invented by Clark Allan Crane A Leftist Tree is a priority queue It satisfies the leftist structural property For any node X Leftist Tree, Rightmost path is the Shortest

Null Path Length denoted by npl(X) Length of shortest path from X to an external nodenpl(NULL) = -1 If X has zero or one child, npl(X) = 0 Otherwisenpl(X) = 1 + min { npl(leftChild(X)), npl(rightChild(X))}

Null Path Length1 1 0

0 0 -1 -1

0 -1 0

0 -1 Null -1 Null

-1 Null

Null Null Null -1 -1 Null Null -1 Null

npl(NULL) = -1

if X has zero or one child npl(X) = 0 else npl(X) = 1 + min{ npl( leftChild(X) ), npl( rightChild(X) ) }

Structural Property Height-biased Leftist Property X HBLT npl(leftChild(X)) npl(rightChild(X))

Tree is unbalanced Biased towards left Left paths are long, giving the name Leftist Tree Rightmost path is the shortest

Structural PropertyT1 2 1 0 0 0 0 1 0 0 1 0 0 0 T2 2 1*Leftist Heap Property Violated npl(leftChild) < npl(rightChild)

1

Null path lengths: T1 is a Height-biased Leftist Tree, T2 is not

Leftist Heap A Heap-ordered Leftist Tree

Heap-order Property Min Leftist Heap X Heap key(X) key(Parent(X))

Max Leftist Heap X Heap key(X) key(Parent(X))

If X is root Parent (X) = root

Binary Heap vs. Leftist HeapBinary Heap Perfectly balanced Operations BuildHeap FindMin Merge Insert DeleteMin Binary Heap O(N) O(1) (N) O(log N) O(log N)

Leftist Heap Very unbalanced Leftist Heap O(N) O(1) O(log N) O(log N) O(log N)

Binary Heap vs. Leftist HeapBinary Heap Perfectly balanced Operations BuildHeap FindMin Merge Insert DeleteMin Binary Heap O(N) O(1) (N) O(log N) O(log N)

Leftist Heap Very unbalanced Leftist Heap O(N) O(1) O(log N) O(log N) O(log N)

Merge is expensive in ordinary Heaps

TheoremThe number of nodes N in a leftist tree with r nodes on the right path is 2r -1Proof is by Induction

This givesN 2r 1 r log2 (n + 1)

Structure of a Node

Left Data Pointer

NPL

Right Pointer

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 TreeExtended Binary Tree

A pointer to the root of the leftist tree is also maintained

Extended Binary TreeGiven: A Binary Tree TB For all empty subtrees TB replace each empty subtree with an external node

Binary TreeInternal Node

Replace each empty subtree with an external node

Extended Binary TreeSince an External Node represents NULL

npl(External Node) = -1

1

1

0

Internal Node -1

0

0

0

0

-1 -1

-1 -1

0 External Node

-1

-1

-1

-1

Replace each empty subtree with an external node The number outside each node X is the npl(X)

Operations BuildHeap FindMin Merge Insert DeleteMin O(N) O(1) O(log N) O(log N) O(log N)

General Idea All insertions and merges are performed on the rightmost path containing at most log2 (n + 1) nodes This may violate Leftist Heap Property Leftist Heap Property can be easily restored

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 LeftistIf 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.e If npl( leftChild(H1) ) < npl( rightChild(H1) ) then swap children of H1 npl(H1) = npl(rightChild(H1)) + 1

Merge H1 & H2H1 2 2 H2

21 1 1

31

60 0 0

90 0

50 0

80

7

13

170

37 41

15

110

190

23 26

29

Both H1 and H2 are Min Leftist Heaps

Merge H1 & H2H1 H1 2 2 H2 H2

21 1

Both H1 and H2 are not NULL1 1 1

2

31

60 0 0 0 0 0

90 0 0

50 0

80

7

13

170 0

37 41

15

110

190

23 26

29

Merge (H1, H2) Compare root(H1) '2' & root(H2) '3' H1 has smaller root

Merge H1 & H2H1 2 2 2 H1 1 1 H2

21

31

60 0 0 0 0

90 0 0

50 0

80

7

13

170 0

37 41

15

110

190

23 26

29

Since, leftChild(H1) NULL H1 now points to its rightChild

Merge H1 & H2H2 2

21

Both H1 and H2 are not NULLH1 1 1

2

31

60 0 0

90 0

50 0

80

7

13

170

37 41

15

110

190

23 26

29

Merge (H1, H2) Compare root(H1) '9' & root(H2) '3' H2 has smaller root swap(H1, H2) Now, root(H1) = '3' & root(H2) = '9'

Merge H1 & H2H2 2 1 H1 2 2

21

90 0

60 0

3

178 81 1

370

7

1315 150 0

5 5

1 1

4123 230 0

11 11

0 0

29 29

0 0

19 19

0 0

26 26

0 0

Resizing H1

Merge H1 & H2H2 2 1 H1 2

21

90 0

60 0 1

31

170

37 41

7

13 50 0 0

80

15

110

190

23 26

29

Since, leftChild(H1) NULL H1 now points to its rightChild

Merge H1 & H2H2 2

21

Both H1 and H2 are not NULL2 0 H1 1

1

90

60 0 1

3 13 50 0 0

170

37 41

7

80

15

110

190

23 26

29

Merge (H1, H2) Compare root(H1) '8' & root(H2) '9' H1 has smaller root

Merge H1 & H2H2 2 1

21 2 0 H1 1

90

60 0 1

3 13 50 0 0

170

37 41

7

80

15

110

190

23 26

29

Since, leftChild(H1) NULL H1 now points to its rightChild

Merge H1 & H2H2 2

21

Both H1 and H2 are not NULL2 0

1

90

0 H2091 17 37410

60 0 1

31

170 H1 0

37 41

7

13 50 0 0

8 110

15

190

23 26

29

Merge (H1, H2) Compare root(H1) '23' & root(H2) '9' H2 has smaller root swap(H1, H2) Now, root(H1) = '9' & root(H2) = '23'

Merge H1 & H2H2 2 0

21 2 0

23 3 261

0 H2091 17 37410

60 0 1

7

13 50 0 0

81

H1

15

110 0

19 29 290

90

170

37 41

Resizing H1

Merge H1 & H2H2 2 0

21 2 0

23 3 261

0 H2091 17 37410

60 0 1

7

13 50 0 0

81

H1

15

110

190

90

29

170

37 41

Since, leftChild(H1) NULL H1 now points to its rightChild

Merge H1 & H2H2 2

21

Both H1 and H2 are not NULL2 0

0

23 26

0 H2091 17 37410

60 0 1

31

7

13 50 0 0

81

15

110

190

90

H1

29

170

37 41

Merge (H1, H2) Compare root(H1) '37' & root(H2) '23' H2 has smaller root swap(H1, H2) Now, root(H1) = '23' & root(H2) = '37'

Merge H1 & H2H2

2

0

21 2

370

0 H2091 17 37410

60 0 1

31

418

7

13 50 0 0

1

15

110

190

90

H1

29

170

23 26

NULL

Since, leftChild(H1) NULL H1 now points to its rightChild NULL

Merge H1 & H2H2

2

21 2

H1 is NULL0

0

37 41

60 0 1

31

7

13 50 0 0

81

15

110

190

90

29

170

23 26

H1

NULL

Merge (H1, H2) Since root(H1) is 'NULL' swap(H1, H2) Now, root(H1) = '37' & root(H2) = 'NULL'

Merge H1 & H2H2

2

21 2

H2 is NULL NULL3

60 0 1

1

7

13 50 0 0

81

15

110

190

90

Adjust Null Path Lengths from the Last Node on the Rightmost Path to the RootH1

29

170

230

26 370

41

NULL

Merge H1 & H22

Leftist Heap Property NOT Violated

21 2

60 0 0 1

31

7

13 5 15

Adjust Null Path Lengths H1 points to '37' 0 0 1 from the Last Node 11 19 9 on the Rightmost Path 0 0 0 to the Root H1 29 17 2300 0 0 0

8

26 37

41

NULL

npl (NULL) = -1

leftChild(H1)npl rightChild(H1)npl 0 -1 H1npl = rightChild(H1)npl + 1 = '0'

Merge H1 & H22

Leftist Heap Property NOT Violated

21 2

60 0 1

31

7

13 50 0 0

81

H1 moves up to '23'0 1 0*

15

110

190

9 170

29

230

H1

26 370

41

NULL

npl (NULL) = -1

leftChild(H1)npl rightChild(H1)npl 0 0 H1npl = rightChild(H1)npl + 1 = '1'

Merge H1 & H22

21 2

Leftist Heap Property Violated swap( leftChild(H1), rightChild(H1) )

60 0 1

31

7

13 50 0 0

8

1* 190

H1 moves up to '9'H1 1 1

15

110

19 29 17

230 0

26 370

41

leftChild(H1)npl rightChild(H1)npl 0 1

Merge H1 & H22

21 2

Leftist Heap Property Violated swap( leftChild(H1), rightChild(H1) )

60 0 1

31

7

13 50 0 0

8

H1

1 1*90 1

H1 moves up to '9'

15

110

19 29 17

230 0

26 370

41

leftChild(H1)npl rightChild(H1)npl 0 1 H1npl = rightChild(H1)npl + 1 = '1'

Merge H1 & H22

21 2

Leftist Heap Property Violated swap( leftChild(H1), rightChild(H1) )

60 0 1

3 13 50 0 0 0

1 1* 181 1

7

H1

H1 moves up to '8'0 0

15

110 0

191 1

9 2317 170 0

29 290 0

26 37 26 37 41 410 0

leftChild(H1)npl rightChild(H1)npl 0 1 H1npl = rightChild(H1)npl + 1 = '1'

Merge H1 & H22

Leftist Heap Property NOT Violated

21 2

60 0 1

3 13 50 0 0 1

H1

1 180

7

H1 moves up to '3'

15

111

90 0

19 17 29

230 0

26 370

41

leftChild(H1)npl rightChild(H1)npl 1 1 H1npl = rightChild(H1)npl + 1 = '2'

Merge H1 & H22* 22

21 2

Leftist Heap Property Violated swap( leftChild(H1), rightChild(H1) )H1

60 0 1

31

7

13 50 0 0

80

H1 moves up to '2'

15

111

90 0

19 17 29

230 0

26 370

41

leftChild(H1)npl rightChild(H1)npl 1 2 H1npl = rightChild(H1)npl + 1 = '2'

Merge H1 & H2Root 2 2 H1

22 1

31 1 0

60

50 0 0

8 111

70

13

15

90 0

19 17 29

H1 is returned Root pointer now points to H1

230 0

26 370

41

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 rootIf Leftist Heap Property is violated i.e If 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 3H1 2 H2

21 1

0

3 9

60 0 0

0

7

13

170

37 41

H1 existing Heap H2 one-node heap containing node to be inserted Both H1 and H2 are Min Leftist Heaps

Insert 3H1 H1 2 2 H2

21 1

Both H1 and H2 are not NULL1 1

0

3

60 0 0 0 0 0

90 0

7

13

170 0

37 41

Merge (H1, H2) Compare root(H1) '2' & root(H2) '3' H1 has smaller root

Insert 3H1 2 H2

21 1

0 H1

3

60 0 0

90

7

13

170

37 41

Since, leftChild(H1) NULL H1 now points to its rightChild

Insert 3H2 2

21

Both H1 and H2 are not NULLH1 1

0

3

60 0 0

90

7

13

170

37 41

Merge (H1, H2) Compare root(H1) '9' & root(H2) '3' H2 has smaller root swap(H1, H2) Now, root(H1) = '3' & root(H2) = '9'

Insert 3H2 2 2

21 1 0 0

1 H1 0

90

60 0 0 0 1

3 3 130

170

37 41

7

9 NULL0

170

37 41

Since, leftChild(H1) == NULL leftChild(H1) = H2

Insert 3H2 2

Adjust Null Path Lengths 2 from the last node 1 0 on the Rightmost Path 6 3 to the Root0 0 1

H2 is NULLH1

NULL

7

130

90

170

37 41

Insert 32

Adjust Null Path Lengths from the last node on the Rightmost Path to the Root

21 0

H1

H1 points to '3'

60 0 1

3 130

7

90

NULL370

npl (NULL) = -1

Leftist Heap Property NOT Violated

17

41

leftChild(H1)npl rightChild(H1)npl 1 -1 H1npl = rightChild(H1)npl + 1 = '0'

Insert 32 1 2*

21 0

H1

H1 moves up to '2'

60 0 1

3 130

7

90

NULL370

npl (NULL) = -1

Leftist Heap Property NOT Violated

17

41

leftChild(H1)npl rightChild(H1)npl 1 0 H1npl = rightChild(H1)npl + 1 = '1'

Insert 3Root 1 1 H1

21 0

H1 is returned Root pointer now points to H1

60 0 1

3 130

7

90

170

37 41

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

DeleteMinRoot 2

21 1

60 0 0

90

7

13

170

37 41

Delete Minimum Key '2'

DeleteMinoldRoot Root 2 2 H1 1

2 21

H2

60 0 0

90

7

13

170

37 41

Save old value of root H1 = rootleftChild H2 = rootrightChild

DeleteMinoldRoot 2 H1 1

2

H2 1

60 0

Both H1 and H2 are not NULL0

90

7

13

170

37 41

Merge (H1, H2) Compare root(H1) '6' & root(H2) '9' H1 has smaller root

DeleteMinoldRoot 2 H1 1

21 H1 0 0

H2

60

90

7

13

170

37 41

Since, leftChild(H1) NULL H1 now points to its rightChild

DeleteMinoldRoot 2

21

H2 1

60 0

Both H1 and H2 are not NULLH1 0

90

7

13

170

37 41

Merge (H1, H2) Compare root(H1) '9' & root(H2) '3' H2 has smaller root swap(H1, H2) Now, root(H1) = '3' & root(H2) = '9'

DeleteMinoldRoot 2

21 0 H1 1

H2

60

13

70

90

170

37 41

Since, leftChild(H1) NULL H1 now points to its rightChild

DeleteMinoldRoot 2

21

H2 0

60 1

Both H1 and H2 are not NULL9H1 0

13

70

170

37 41

Merge (H1, H2) Compare root(H1) '37' & root(H2) '13' H2 has smaller root swap(H1, H2) Now, root(H1) = '37' & root(H2) = '13'

DeleteMinoldRoot 2

21 0

H2

60 1 0 H1 0

37 9 41

70

170

13

37 NULL0

41

Since, leftChild(H1) == NULL leftChild(H1) = H2

DeleteMinoldRoot 2

Adjust Null Path Lengths from the last node 1 on the Rightmost Path 6 to the Root0 1

2

H2

H2 is NULLH1 0

NULL

70

9 170

13 370

41

DeleteMinoldRoot 2

Adjust Null Path Lengths from the last node on the Rightmost Path to the Root0

21

H1 points to '13'

61

70

90

H1

Leftist Heap Property NOT Violated

170

13 370

NULL

npl (NULL) = -1

41

leftChild(H1)npl rightChild(H1)npl 0 -1 H1npl = rightChild(H1)npl + 1 = '0'

DeleteMinoldRoot 2

21

H1 moves up to '9'

60 1

70

90

H1

Leftist Heap Property NOT Violated

170

13 370

NULL

npl (NULL) = -1

41

leftChild(H1)npl rightChild(H1)npl 0 0 H1npl = rightChild(H1)npl + 1 = '1'

DeleteMinoldRoot 2

21 1 1*

H1

H1 moves up to '6'H1

60 0 1 1

70 0

90 0

17 Leftist Heap Property Violated swap( leftChild(H1), rightChild(H1) )0 0

130 0

37

41

leftChild(H1)npl rightChild(H1)npl 0 1 H1npl = rightChild(H1)npl + 1 = '1'

DeleteMinoldRoot 2 Root 1 1

2

H1

61 0

90 0

7 13

170

H1 is returned Root pointer now points to H1 Delete old value of Root

370

41

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 H Insert( H )

Brute Force BuildHeap0 0 0 0 0 0 0

7

9

37

41

2

6

13

Build a min leftist heap containing elements 7, 9, 37, 41, 2, 6, 13 Create 7 one-node min leftist heaps and insert them in a queue |Q| = 7

Brute Force BuildHeapRoot 0 0 0 0 0 H 0 0 0 0 0

7 70 0

9 9

37

41

2

6

13

9 9

Root = 7 H=9 Insert( H )

|Q| = 6 |Q| = 5

Brute Force BuildHeapRoot 0 1 0 0 H 0 0 0 0

70 0

37 37

41

2

6

13

9

37

Root = 7 H = 37 Insert( H )

|Q| = 5 |Q| = 4

Brute Force BuildHeapRoot 1 1 0 H 0 0 0

70 0

41

2

6

13

90

37 41

Root = 7 H = 41 Insert( H )

|Q| = 4 |Q| = 3

Brute Force BuildHeapRoot 1 0 0 0 H 0 0

7 21 1 0

2 20

6

13

7 90 0 0 0

3737 41

90 0

41

Root = 7 H=2 Insert( H )

|Q| = 3 |Q| = 2

Brute Force BuildHeapRoot1 1 0

H 0 0 0

2 21 1 1 0 0

6 66

13

7 70 0 0 0 0 0

9 90 0 0

37 37 41 41

Root = 7 H=6 Insert( H )

|Q| = 2 |Q| = 1

Brute Force BuildHeapRoot 1 1 0 0 H

21 1 1 0 0 0

13 13

7 70 0 0 0 0 0

6 60 0

9 9 37 37 130 0 0

41 41

Root = 7 H = 13 Insert( H )

|Q| = 1 |Q| = 0

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 H2 Merge H1 and H2 Insert merged min leftist heap into queue

Efficient BuildHeap0 0 0 0 0 0 0

7

9

37

41

2

6

13

Build a min leftist heap containing elements 7, 9, 37, 41, 2, 6, 13 Create 7 one-node min leftist heaps and insert them in a queue |Q| = 7

Efficient BuildHeapH1 0 0 0 0 H2 0 0 0 0 0 0

7 70

9 9

37

41

2

60

7 9

13

9

Remove and merge first two min leftist heaps from queue H1 = 7 |Q| = 6 H2 = 9 |Q| = 5 H1 = Merge(H1, H2) Insert H1 into queue |Q| = 6

Efficient BuildHeapH1 0 0 0 0 H2 0 0 0 0 0

37 370

41 41

2

6

130

370

7 9

41

41

Remove and merge first two min leftist heaps from queue H1 = 37 |Q| = 5 H2 = 41 |Q| = 4 H1 = Merge(H1, H2) Insert H1 into queue |Q| = 5

Efficient BuildHeapH1 0 0 0 0 H2 0 0 0 0

2 20

6 6

130

70

20

37

6

9

6

41

Remove and merge first two min leftist heaps from queue H1 = 2 |Q| = 4 H2 = 6 |Q| = 3 H1 = Merge(H1, H2) Insert H1 into queue |Q| = 4

Efficient BuildHeapH1 0 1 0 0 H2 0 1 0

13 7 130 0 0

70

370

700

2 6 13

9

13 9

41

9

Remove and merge first two min leftist heaps from queue H1 = 13 |Q| = 3 H2 = 7 |Q| = 2 H1 = Merge(H1, H2) Insert H1 into queue |Q| = 3

Efficient BuildHeapH1 1 0 0 1 H2 1

2 370 0 0

20

200

70

41 60

37 6 41

60

937 13 41

Remove and merge first two min leftist heaps from queue H1 = 37 |Q| = 2 H2 = 2 |Q| = 1 H1 = Merge(H1, H2) Insert H1 into queue |Q| = 2

Efficient BuildHeapH1 1 1 1 1 H2

2 70 1 0 0 1

20 0 0

20 0

9 70 0

13 7 60 0

660 0

37

90

13 90

13 41 37

370 0

41

41

Remove and merge first two min leftist heaps from queue H1 = 7 |Q| = 1 H2 = 2 |Q| = 0 H1 = Merge(H1, H2) Insert H1 into queue |Q| = 1

Efficient BuildHeapRoot 1

21 0

70 0

6 13

90

370

41

Since |Q| > 0 Root = 2

Time Complexity of Efficient BuildHeapAssume min leftist heap contains N = 2k elementsMerge Operations Recursive Calls to Merge

N/2 N/4 N/8 N/2k = 1

1 2 3

k

Time Complexity of Efficient BuildHeapTotal Time for BuildHeap= = = = N N N N ( * 1) + ( * 2) + ( * 3) + + ( k * k) 2 4 8 2 1 1 1 1 N ( + + + k) 2 4 8 2 k i N i i=1 2 i N i i=1 2

= 3n for n 3 = (N)