Cis435 week05

Preview:

Citation preview

Data Structures & Algorithms

Heapsort

Heaps

A heap is data structure that can be viewed as a nearly complete binary tree

Each node corresponds to an element of an array that stores its values

The tree is completely filled on all levels except the lowest

2 4 1

8 7 9 3

1414 10

16

Heaps

Heaps are typically stored using arrays The array is of size length(A) heapsize(A) elements are currently in use

A[1] is the “root” node of the tree Any element x has the following properties:

Parent(x) is x/2 Left(x) is 2*x Right(x) is 2*x+1

16 14 10 8 7 9 3 2 4 1

1 2 3 4 5 6 7 8 9 10

The Heap Property

Heaps satisfy what is known as the heap property: For a max-heap, the heap property is:

A[Parent(x)] >= A[x] I.e., the root node of the tree or any subtree

has a larger value than any node in its subtrees

This is reversed for min-heaps: A[Parent(x)] <= A[x] I.e., the smallest element is at the root

Terminology

Height of a node = number of edges that must be traversed to get from that node to a leafHeight of a tree = height of the root = O(lg n)Basic heap operations generally take O(lg n), because they are based on the height of the tree

Maintaining the Heap Property

MaxHeapify is a routine used to maintain the max-heap property of an array It takes as input the array to heapify, the

element to begin with, and the number of elements in the heap

Assumes Left(x) and Right(x) are heaps, but the tree rooted at x may not be, thus violating the heap property

The idea is to propagate x through the tree into it’s proper position

MaxHeapify

MaxHeapify(A, x, heapsize){

L = Left(x)R = Right(x) if ( L < heapsize && A[L] > A[x] )

Largest = Lelse

Largest = xif ( R <= heapsize && A[R] > A[Largest] )

Largest = Rif ( Largest != x ){

swap(A[x], A[Largest])MaxHeapify(A, Largest, heapsize)

}}

MaxHeapify In Action

Here, the red node is out of place, violating the heap property

2 8 1

14 7 9 3

144 10

16

MaxHeapify In Action

After calling MaxHeapify(A, 2, 10), the red node is pushed further down the heap

2 8 1

4 7 9 3

1414 10

16

MaxHeapify In Action

After calling MaxHeapify(A, 4, 10), the heap is now correct – a further call to MaxHeapify(A, 9, 10) will yield no further changes

2 4 1

8 7 9 3

1414 10

16

Building a Heap

Given an unsorted array, we can build a heap recursively from the bottom-up using this algorithm:

BuildMaxHeap(A, size){

for ( x = length(A)/2 ; x >= 1 ; --x )MaxHeapify(A, x, size)

}

BuildMaxHeap(A, size){

for ( x = length(A)/2 ; x >= 1 ; --x )MaxHeapify(A, x, size)

}

Building a Heap

14 8 7

2 16 9 10

141 3

4

1

2 3

4 5 6 7

8 9 10

Building a Heap

14 8 7

2 16 9 10

141 3

4

1

2 3

4 5 6 7

8 9 10

Building a Heap

2 8 7

14 16 9 10

141 3

4

1

2 3

4 5 6 7

8 9 10

Building a Heap

2 8 7

14 16 9 3

141 10

4

1

2 3

4 5 6 7

8 9 10

Building a Heap

2 8 7

14 1 9 3

1416 10

4

1

2 3

4 5 6 7

8 9 10

Building a Heap

2 8 1

14 7 9 3

1414 10

16

1

2 3

4 5 6 7

8 9 10

Analysis of BuildMaxHeap

How long does it take? MaxHeapify has cost O(lgn), and is called O(n)

times, so intuitively there’s O(nlgn) This isn’t an asymptotically tight bound, though

The MaxHeapify cost isn’t really based on n It’s cost is based on the height of the node in the tree An n-element heap has height lgn, and at most n/2h+1

nodes of any height h

The math at this point gets a bit complicated, but results in a running time of O(n) (see pg. 145 (old)/135 (new))

The HeapSort Algorithm

The HeapSort algorithm sorts an array by using a max-heap as an intermediate step First, a max-heap is built from the input The max element is exchanged with

A[heapsize], to put it in its final position The remainder of the array is then re-

heapified, using heapsize - 1

The HeapSort Algorithm

HeapSort(A, size){BuildHeap(A, size)For ( x = size ; x >= 2 ; --x ){

swap(A[1], A[x])--heapsizeHeapify(A, 1, x-1)

}}

What is the running time of HeapSort?What is the running time of HeapSort?

Analysis of HeapSort

In practice, the HeapSort will usually be beat by QuickSortThe heap data structure has a number of other uses, however

Priority Queues

One use of a heap is as a priority queuePriority queues are often used in an OS to perform job/resource scheduling Also in simulators, and many other tasks

A priority queue is a data structure for maintaining a set of elements (S), each with an associated value called a key Priority queues come in two flavors: max-

priority queues and min-priority queues

Priority Queues

Max-priority queues support these operations: Insert(S, x) – inserts x into S Maximum(S) – returns the element in S with

the largest key ExtractMax(S) – removes and returns the

element in S with the largest key IncreaseKey(S, x, k) – increases the value of

element x’s key to the new value k

Priority Queuess

HeapMaximum(A){ return A[1];}

Priority Queues

HeapExtractMax(A, heapsize){ if ( heapsize < 1 ) throw HeapUnderflowError(); max = A[1]; A[1] = A[heapsize]; --heapsize; MaxHeapify(A, 1, heapsize); return max;}

Priority Queues

HeapIncreaseKey(A, i, key){ if ( key < A[i] ) throw HeapKeyError(); A[i] = key; while ( i > 1 && A[Parent(i) < A[i] ) { swap(A[i], A[Parent(i)]); i = Parent(i); }}

Priority Queues

MaxHeapInsert(A, key, heapsize){ ++heapsize; A[heapsize] = -MAXKEY; HeapIncreaseKey(A, A[heapsize], key);}

Exercises

1st Edition: Pg 142: 7.1-1, 7.1-2, 7.1-6 Pg 144: 7.2-1, 7.2-2, 7.2-4 Pg 150: 7.5-3, 7.5-5

2nd Edition Pg 129: 6.1-1, 6.1-2, 6.1-6 Pg 132: 6.2-1, 6.2-3, 6.2-5 Pg 142: 6.5-6, 6.5-7

Recommended