Trees IV The Heap heaps 1 Heap Like

  • Slides: 19
Download presentation
Trees IV: The Heap heaps 1

Trees IV: The Heap heaps 1

Heap • Like a binary search tree, a heap is a binary tree in

Heap • Like a binary search tree, a heap is a binary tree in which the data entries can be compared using total order semantics • Defining qualities of a heap: – the data entry contained in any node is greater than or equal to the data entry contained in either of its children – the tree is always complete heaps 2

Heap Example 45 32 19 10 41 7 28 40 12 heaps 3

Heap Example 45 32 19 10 41 7 28 40 12 heaps 3

Heap Applications • Heap can be used to implement a sorting algorithm called heapsort

Heap Applications • Heap can be used to implement a sorting algorithm called heapsort • Heap is also a handy way to implement a priority queue -- we’ll use this application to illustrate how heaps work heaps 4

Heap Implementation • Because a heap is by definition a complete tree, it is

Heap Implementation • Because a heap is by definition a complete tree, it is easy to use an array-based implementation • Heap operations re. Heap. Up and re. Heap. Down are used to maintain the other defining quality of a heap -- each node’s data entry >= data entries of its children heaps 5

Re. Heap. Up operation 45 When a new node is added to the tree,

Re. Heap. Up operation 45 When a new node is added to the tree, it is always added at the leftmost open position in 19 the bottom row 10 32 41 7 12 28 35 heaps 40 This maintains completeness of tree, but can violate the other defining characteristic of a heap 6

Re. Heap. Up operation Re. Heap. Up restores the 45 second heap condition: a

Re. Heap. Up operation Re. Heap. Up restores the 45 second heap condition: a parent node’s data is always greater than 32 35 or equal to the data in either of 19 32 35 7 its child nodes 10 12 35 7 heaps Parent/child data swapping continues until the heap condition is restored 41 28 40 The operation is accomplished by swapping the new node’s data entry with that of its parent 7

Re. Heap. Down operation In a priority queue, the highest-priority item is always dequeued

Re. Heap. Down operation In a priority queue, the highest-priority item is always dequeued first -this item would be the top item of 19 the heap 10 12 45 7 32 35 41 35 32 7 28 35 45 7 heaps Since this is going to be an array implementation, we’ll perform the usual trick of swapping the last array entry with the first, so we can 40 minimize the amount of copying to be done 8

Re. Heap. Down operation Now we can effectively 45 41 7 remove the item

Re. Heap. Down operation Now we can effectively 45 41 7 remove the item by simply diminishing the “used” portion 35 32 of our array by 1 (already 19 35 32 7 done here) 10 12 41 40 7 28 We are once again faced with the same problem -the heap is the right shape, but the data values are in the wrong positions 40 7 We solve this problem, as before, by swapping data between nodes. In this case, we swap the parent node’s data with the largest data entry of the two children, continuing until the heap is restored. heaps 9

Example: Priority Queue with heap implementation • Priority queue has all operations associated with

Example: Priority Queue with heap implementation • Priority queue has all operations associated with a queue: enqueue, dequeue and helper functions (e. g. size( ), is_empty( ), etc. ) • Heap is a good fit for priority queue because highest-priority item should always be dequeued first, and this item would always be found at the top of a heaps 10

Code for Priority Queue template <class thing> class PQheap { public: PQheap( ); enum

Code for Priority Queue template <class thing> class PQheap { public: PQheap( ); enum {SIZE=30}; void enqueue (const thing& entry); thing dequeue( ); size_t size( )const {return num. Items; }. . . heaps 11

Code for Priority Queue private: thing data[SIZE]; size_t num. Items; void re. Heap. Up(size_t

Code for Priority Queue private: thing data[SIZE]; size_t num. Items; void re. Heap. Up(size_t n); void re. Heap. Down(size_t n); size_t parent(size_t n) const {return (n-1)/2; } size_t left_child(size_t n) const {return (2*n)+1; } size_t right_child(size_t n) const {return (2*n)+2; } void Swap (thing& x, thing& y); }; heaps 12

Code for Priority Queue template <class thing> PQheap<thing>: : PQheap() { num. Items=0; }

Code for Priority Queue template <class thing> PQheap<thing>: : PQheap() { num. Items=0; } heaps 13

Code for Priority Queue template <class thing> void PQheap<thing>: : enqueue (const thing& entry)

Code for Priority Queue template <class thing> void PQheap<thing>: : enqueue (const thing& entry) { assert (size( ) < SIZE); data[num. Items] = entry; re. Heap. Up(num. Items); num. Items++; } heaps 14

Code for Priority Queue template<class thing> void PQheap<thing>: : re. Heap. Up(size_t n) {

Code for Priority Queue template<class thing> void PQheap<thing>: : re. Heap. Up(size_t n) { size_t x = n; while (x>0 && data[x]> data[parent(x)]) { Swap(data[x], data[parent(x)]); x=parent(x); } } heaps 15

Code for Priority Queue template <class thing> void PQheap<thing>: : Swap (thing& x, thing&

Code for Priority Queue template <class thing> void PQheap<thing>: : Swap (thing& x, thing& y) { thing temp = x; x = y; y = temp; } heaps 16

Code for Priority Queue template <class thing> thing PQheap<thing>: : dequeue() { thing value=data[0];

Code for Priority Queue template <class thing> thing PQheap<thing>: : dequeue() { thing value=data[0]; // save return value num. Items--; data[0]=data[num. Items]; // swap top & bottom re. Heap. Down(num. Items); // restore heap return value; } heaps 17

Code for Priority Queue template <class thing> void PQheap<thing>: : re. Heap. Down(size_t n)

Code for Priority Queue template <class thing> void PQheap<thing>: : re. Heap. Down(size_t n) { size_t current = 0, big_child, heap_ok = 0; while ((!heap_ok) && (left_child(current) < n)) { if (right_child(current) >= n) big_child = left_child(current); else if (data[left_child(current)] > data[right_child(current)]) big_child = left_child(current); else big_child = right_child(current); . . . heaps 18

Code for Priority Queue if (data[current] < data[big_child]) { Swap(data[current], data[big_child]); current = big_child;

Code for Priority Queue if (data[current] < data[big_child]) { Swap(data[current], data[big_child]); current = big_child; } else heap_ok = 1; } // end of while loop } // end of function heaps 19