Height-Biased Leftist Heaps Advanced)

Post on 13-Nov-2014

126 views 1 download

Tags:

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