Heaps and Heap Sort - Naval Postgraduate...

30
1 Heaps and Heap Sort

Transcript of Heaps and Heap Sort - Naval Postgraduate...

1

Heaps and Heap Sort

2

Sample Heap

90

84 44

12 5 3877

17 23

0

1 2

3 4 5 6

7 8

root

index

left child of 44

right child of 44

Level #

1

2

3

4

3

Heap Constraints

• A heap must satisfy the following two constraints:

– Structural Constraint: Nodes in a heap with N nodes must occupy the positions numbered 0, 1, ..., N-1.

– Value Relationship Constraint: A value stored in a node must be larger than the maximum of the values stored in its left and right children.

4

Nonheaps

Heaps

Structural Constraints

• Sample heaps and nonheaps that violate the structural constraints:

5

Nonheaps

Heaps

Value Relationship Constraints

• Sample heaps and nonheaps that violate the value relationship constraints:

45

25 16

3 1222

45

12 34

11 229

90

35 24

13 1612

45

55 16

3 1258

45

25 33

34 2322

45

25 55

3 1222

6

Heap ADTpublic interface NPSHeap<E> { /** Maintains the Heap properties */ public void heapify(int i); /** Converts a non-heap array into a heap */ public void buildHeap(); /** Insert an item into the heap, such that the heap property is maintained */ public void add(E item); /** Returns, but does not remove, the root element in the heap */ public E peek() throws NPSHeapEmptyException ; /** Removes and returns the root element of the heap. * Maintains the heap property */ public E poll() throws NPSHeapEmptyException ; /** Returns the size of the heap */ public int size();

/** Clears the heap */ public void clear(); /** Tells whether or not the heap is empty */ public boolean isEmpty(); }

7

Heapify

• When heapify(i) is called, it’s assumed that the binary trees rooted at the left and right children of i are heaps, but that node i may be smaller than its children

4

14

82

7

1

16

10

9 3

i

8

Heapify

• At each step, if node i is smaller than either of its children, it is swapped with the larger of the two.

4

14

82

7

1

16

10

9 3

i

9

Heapify

• At each step, if node i is smaller than either of its children, it is swapped with the larger of the two.

4

14

82

7

1

16

10

9 3

i

10

Heapify

• At each step, if node i is smaller than either of its children, it is swapped with the larger of the two.

14

4

82

7

1

16

10

9 3

i

11

Heapify

• At each step, if node i is smaller than either of its children, it is swapped with the larger of the two.

14

8

42

7

1

16

10

9 3

i

12

Build Heap

23

17 5

12 44 3890

84 77

0

1 2

3 4 5 6

7 8

Before

23

17 5

12 44 3890

84 77

0

1 2

3 4 5 6

7 8

3

(9-2)/2 = 323

17 5

12 44 3890

84 77

0

1 2

3 4 5 6

7 8

2

23

17 44

12 5 3890

84 77

0

1 2

3 4 5 6

7 8

123

90 44

12 5 3884

17 77

0

1 2

3 4 5 6

7 8

0

90

84 44

12 5 3877

17 23

0

1 2

3 4 5 6

7 8

Done

• We can apply heapify in a bottom-up manner to convert an array into a max-heap.

• Heapify is applied from position (N-2)/2 to position 0.

13

Adding an Element

• When we add an element to a heap, we place it in the first available position (I.e., after all other nodes), and then perform an up-heap procedure to restore the heap properties, swapping nodes if the child is smaller than its parent.

14

8

42

7

1

16

10

9 3

15

14

Adding an Element

• When we add an element to a heap, we place it in the first available position (I.e., after all other nodes), and then perform an up-heap procedure to restore the heap properties, swapping nodes if the child is smaller than its parent.

14

8

42

15

1

16

10

9 3

7

15

Adding an Element

• When we add an element to a heap, we place it in the first available position (I.e., after all other nodes), and then perform an up-heap procedure to restore the heap properties, swapping nodes if the child is smaller than its parent.

15

8

42

14

1

16

10

9 3

7

16

90

84 44

12 5 3877

17 23

0

1 2

3 4 5 6

7 8

0 1 2 3 4 5 6 7 8

90

9023

84 44

12 5 3877

17

0

1 2

3 4 5 6

7

0 1 2 3 4 5 6 7 8

90

23 > max{84, 44}? NO, so swap.

84

23 44

12 5 3877

17

0

1 2

3 4 5 6

7

0 1 2 3 4 5 6 7 8

90

23 > max{77, 12}? NO, so swap.

84

77 44

12 5 3823

17

0

1 2

3 4 5 6

7

0 1 2 3 4 5 6 7 8

90

23 > max{17}? YES, so stop.

84

77 44

12 5 3823

17

0

1 2

3 4 5 6

7

0 1 2 3 4 5 6 7 8

90

Removing the Top Element

• When removing an element, the last element is placed at the root and a heapify is performed.

90

84 44

12 5 3877

17 23

0

1 2

3 4 5 6

7 8

Before After

17

Heap Implementation

• We need to implement the abstract data structure heap into a concrete data structure.

90

84 44

12 5 3877

17 23

0

1 2

3 4 5 6

7 8

Abstract Heap Structure Concrete Implementation

0 1 2 3 4 5 6 7 8

23173851277448490

18

Array Indexing

90

84 44

12 5 3877

17 23

0

1 2

3 4 5 6

7 8

0 1 2 3 4 5 6 7 8

Before

90 84 44 77 12 5 38 17 23 • Implementing a Heap as an array is quite efficient.

• What are the formulas for determining the indices of the left and right children of a node? How about the parent of a node?

19

Heapify

public void heapify(int i) { int largest; int l = left(i); int r = right(i); // Check the left child

if ((l < count) && (comparator.compare(arrayHeap[l], arrayHeap[i]) > 0)) largest = l; else largest = i;

// Check the right child

if ((r < count) && (comparator.compare(arrayHeap[r], arrayHeap[largest]) > 0)) largest = r; if (largest != i) { E tmp = arrayHeap[i]; arrayHeap[i] = arrayHeap[largest]; arrayHeap[largest] = tmp; heapify(largest); }

}

20

buildHeap, add /**

* Create a heap from an arbitrary array

*/

public void buildHeap() {

int i;

for (i = parent(count-1); i >=0; i-- ) {

heapify(i);

}

}

public void add(E item) {

if (count == arrayHeap.length)

expand();

int ind = count;

count++;

while (ind > 0 && comparator.compare(arrayHeap[parent(ind)], item) < 0) {

arrayHeap[ind] = arrayHeap[parent(ind)];

ind = parent(ind);

}

arrayHeap[ind] = item;

}

21

Reminder: NPSPriorityQueue Interface

public interface NPSPriorityQueue<E extends Comparable> {

/** Adds an element to the priority queue */ public void add(E element); /** Removes all elements from the priority queue. */ public void clear( );

/** Determines whether the priority queue is empty or not. */ public boolean isEmpty( );

/** Returns the head element without removing it */ public E peek( ) throws NPSQueueEmptyException;

/** Removes and returns the head element */ public E poll( ) throws NPSQueueEmptyException;

/** Returns the number of elements in the priority queue */ public int size( );}

22

Heap as a Priority Queue

• A heap works quite well as a priority queue.

public class NPSHeapPQ<E> implements NPSPriorityQueue<E> {

NPSHeap<E> heap;

/** Constructor */

public NPSHeapPQ() {

heap = new NPSArrayHeap<E>();

}

public NPSHeapPQ(int size) {

heap = new NPSArrayHeap<E>(size);

}

public NPSHeapPQ(int size, Comparator<E> comparator) {

heap = new NPSArrayHeap<E>(size, comparator);

}

/** Add an element to the heap */

public void add(E element) {

heap.add(element);

}

23

Heap as a Priority Queue /** Clear the heap */ public void clear() { heap.clear(); }

/** Is the heap empty? */ public boolean isEmpty() { return heap.isEmpty(); }

/** Fetch but don’t remove the top element */ public E peek() throws NPSQueueEmptyException { return heap.peek(); }

/** Remove and return the top element */ public E poll() throws NPSQueueEmptyException { return heap.poll(); }

/** size of the priority queue */ public int size() { return heap.size(); }

24

Heapsort Algorithm

• How can we use the heap structure to sort N elements?

• Heapsort is carried out in two phases:

– Construction Phase: Construct a heap with given N elements.

– Extraction Phase: Pull out the value in the root successively, creating a new heap with one less element after each extraction.

25

90

84 44

12 5 3877

17 23

0

1 2

3 4 5 6

7 8

0 1 2 3 4 5 6 7 8

90

9023

84 44

12 5 3877

17

0

1 2

3 4 5 6

7

0 1 2 3 4 5 6 7 8

90

23 > max{84, 44}? NO, so swap.

84

23 44

12 5 3877

17

0

1 2

3 4 5 6

7

0 1 2 3 4 5 6 7 8

90

23 > max{77, 12}? NO, so swap.

84

77 44

12 5 3823

17

0

1 2

3 4 5 6

7

0 1 2 3 4 5 6 7 8

90

23 > max{17}? YES, so stop.

84

77 44

12 5 3823

17

0

1 2

3 4 5 6

7

0 1 2 3 4 5 6 7 8

90

Extraction Phase

• After each extraction, a heap must be rebuilt with one less element. One sample extraction step:

90

84 44

12 5 3877

17 23

0

1 2

3 4 5 6

7 8

0 1 2 3 4 5 6 7 8

Before After

26

90

84 44

12 5 3877

17 23

0

1 2

3 4 5 6

7 8

0 1 2 3 4 5 6 7 8

Rebuild Steps

• A sequence of rebuild steps to sort the list.

90

84 44

12 5 3877

17 23

0

1 2

3 4 5 6

7 8

0 1 2 3 4 5 6 7 8

Before

90

90

84

77 44

12 5 3823

17

0

1 2

3 4 5 6

7

0 1 2 3 4 5 6 7 89084

8477

23 44

12 5 3817

0

1 2

3 4 5 6

0 1 2 3 4 5 6 7 89084

77

77

44

23 38

12 517

0

1 2

3 4 5

0 1 2 3 4 5 6 7 8908477

44

44

38

23 5

1217

0

1 2

3 4

0 1 2 3 4 5 6 7 890847744

38

38

23

17 5

12

0

1 2

3

0 1 2 3 4 5 6 7 89084774438

23

23

17

12 5

0

1 2

0 1 2 3 4 5 6 7 8908477443823

17

17

12

5

0

1

0 1 2 3 4 5 6 7 890847744382317

12

12

5

0

0 1 2 3 4 5 6 7 89084774438231712

5

50 1 2 3 4 5 6 7 8

90847744382317125

Done

Sorting was completedafter 8 rebuild steps.

27

The construct Method

private void construct( ){ for (int i = (heap.length-2) / 2; i >= 0; i--) { current = i; done = false;

while ( !done ) { if ( current has no children ) { done = true; } else { if ( current node < larger child ) { swap the two nodes; set current points to the larger child; } else { done = true; }

} } }}

28

The extract Method

private void extract( ){ for (int size = heap.length-1; size >= 0; size--) { remove the root node data; move the last node to the root;

done = false; //rebuild the heap with one less element while ( !done ) { if ( current has no children ) { done = true; }

else { if ( current node < larger child ) { swap the two nodes; set current points to the larger child; } else { done = true; } }

} }}

29

Heapsort Performance

• The total number of comparisons in the extraction phase is (N-1)×K where K is the depth of a heap.

• We solve for K using the fact that the heap must satisfy the structural constraint:

∑i=1

K

2i−1=2K−1 total # nodes in a heapwith depth K

this holds becauseof the structuralconstraint

2K−1−1<N≤2K−1

K= log 2 N+1 Therefore,

N−1 ×K≃N log2N

30

Heapsort Performance

• There are N/2 rebuild steps in the construction phase.• Each rebuild step will take no more than K comparisons.• The total number of comparsions in the construction

phase is approximately

N2log 2N

Therefore, the total number of comparisons for both phases is

N2log 2N+N log 2N=O N log 2N