300 likes | 384 Views
HEAPS. Review: what are the requirements of the abstract data type: priority queue?. Quick removal of item with highest priority (highest or lowest key value, depending on application.).
E N D
Review: what are the requirements of the abstract data type: priority queue? Quick removal of item with highest priority (highest or lowest key value, depending on application.). What data structures may be used to implement a priority queue? What are the advantages/disadvantages of each? Arrays: removal quick but insertion slow O(log n) to find position but O(n) for shifts Linked lists: removal quick but insertion slow - O(n) to find position and O(1) to relink.
Def. Heap - a binary tree that is: completely filled in reading from left to right across each level, except the last level may not be full, and the key in each node is greater than (or equal to) both of its children’s keys. Note Since the greatest key is always at the top, a heap is a good data structure to implement a priority queue. Although removal is only O(log n) time, insertion is also O(log n) - better than arrays and linked lists.
Note: The highest priority key is always accessible at the top, but removing it produces a hole, which takes the same no. of moves as the height of the tree to fill.
Although we visualize a heap as a linked binary tree, 100 75 50 60 40 45 30 55 15 20 35 25 0 1 2 3 4 5 6 7 8 9 10 11 we usually implement it as an array. 100 25 75 50 60 40 45 30 55 15 20 35
But, a heap provides easy removal of the highest key and easy insertion - both O(log n) using the “trickleup()” and “trickledown()” methods - all that is needed to implement a priority queue. Remember the children of node n are stored in locations: 2n + 1 and 2n + 2 if the first object is stored in location zero in the array but in 2n and 2n+1 when the first object is stored in location one in the array and the first location is left empty. Question: what is the location of the parent of the child at location x? (x - 1)/2 or x/2 if zero is left empty Question: does a heap provide easy searching? no Also, a heap does not provide easy traversal of nodes in order.
“trickledown()” method needed for removal: • After copying node with highest priority, replace it with the last node in the heap. • Now the tree is not a heap! so re-heap • Swap the new root node with the greater of its children. • Repeat that process down to the lowest level. • Remove the root node from the previous sample.
Num 100 25 75 50 60 40 45 30 55 15 20 35 25
Num 100 75 25 50 60 40 45 30 55 15 20 35 25
Num 100 75 60 50 25 40 45 30 55 15 20 35 25
Num 100 75 60 50 55 40 45 30 25 15 20 35 25 0 1 2 3 4 5 6 7 8 9 10 11 75 60 50 55 40 45 30 25 15 20 35 25 NOTE: the last item is not really removed, only the length of the array is decremented.
public Node remove() // delete item with max key { // (assumes non-empty list) Node root = heapArray[0]; heapArray[0] = heapArray[--currentSize]; trickleDown(0); return root; } // end remove()
//what is passed to index? 0 public void trickleDown(int index) { int largerChild; Node top = heapArray[index]; // save root while(index < currentSize/2) // while node has at { // least one child, int leftChild = 2*index+1; int rightChild = leftChild+1; // find larger child if(rightChild < currentSize && // (rightChild exists?) heapArray[leftChild].iData < heapArray[rightChild].iData) largerChild = rightChild; else
largerChild = leftChild; // top >= largerChild? if(top.iData >= heapArray[largerChild].iData) break; // shift child up heapArray[index] = heapArray[largerChild]; index = largerChild; // go down } // end while heapArray[index] = top; // root to index } // end trickleDown()
“trickleup()” method is needed for insertion: • Insert new node at bottom of tree (at heap[heap.length] then increment length. • Compare with parent and swap if needed. • Repeat until root node is reached.
75 60 50 55 40 45 30 90 25 15 20 35
75 60 50 55 40 90 30 45 25 15 20 35
75 60 90 55 40 50 30 45 25 15 20 35
90 60 75 55 40 50 30 45 25 15 20 35
------------------------------------------------------------- ------------------------------------------------------------- public boolean insert(int key) { if(currentSize==maxSize) return false; Node newNode = new Node(key); heapArray[currentSize] = newNode; trickleUp(currentSize++); return true; } // end insert()
public void trickleUp(int index) { int parent = (index-1) / 2; Node bottom = heapArray[index]; while( index > 0 && heapArray[parent].iData < bottom.iData ) { heapArray[index] = heapArray[parent]; // move it down index = parent; parent = (parent-1) / 2; } // end while heapArray[index] = bottom; } // end trickleUp()
Note: trickledown() and trickleup() require the most work for removal and insertion, but that is never more than the no. of levels of the tree. Note: height = log2 n no.node min no.levelsheight 123456789 1223333444444445 0112222333333334 10111213141516 =(int)log2 n No. levels = height + 1
Heapsort - another use of the adt heap. The heap provides a simple and efficient sorting algorithm: • Insert items from an unordered array into a heap then • Remove from the heap and replace in the original array: for (j = 0; j < size; j++) theHeap.insert( anArray[j]); for (j = 0; j < size; j++) anArray[j] = theHeap.remove(); Since insert and remove operate in O(log n) time and each must be executed for every node in the array (n) the heapsort operates in O(n*log n ) time. Quicksort & mergesort What other sorts run in that time?
Question: what is the disadvantage of the heapsort? Space requirement: 2 arrays needed This heapsort algorithm space requirement can be improved by placing the random data into a heap within the same array then: 1. Remove top and hold temporarily. 2. Trickledown() value that was put in place of top. 3. Copy temp to position of last value that had been put in place of top. Question: In what order is the data after this heapsort? Answer: ascending order.
The rightmost node that has children. (Remember: the number of leaves = number of internal nodes +1.) Starting there to convert the random array into a heap with the array itself, trickledown is called about half as many times as it is in the insert() method. To convert an array of random data to a heap within the array itself you may use an iterative approach or a recursive method. Iteratively this would be: for (j = size/2 - 1; j >= 0; j--) theHeap.trickleDown(j) Where in the binary tree is the item with index size/2 - 1?
0 1 2 3 4 5 Random array: Start trickledown here 45 45 45 45 75 50 60 40 60 50 75 50 60 55 75 55 60 55 75 55 40 40 40 50 (only 1 swap needed this time)
0 1 2 3 4 5 75 45 75 45 50 75 50 60 50 60 55 60 55 45 55 40 40 40 The array is now a heap.
0 1 2 3 4 5 Remember remove decrements heap size. 60 40 60 75 60 50 55 50 40 50 60 50 45 55 45 55 45 55 45 40 75 40 75 75 Use the remove() method and insert() at bottom to sort within the array itself. Now trickledown()
60 40 55 40 55 50 45 40 55 50 45 50 40 50 55 50 45 50 40 60 55 60 55 60 45 40 45 60 45 60 75 75 75 75 75 75 Remove biggest and insert at bottom (of what is left of heap) trickledown() Remove biggest and insert at bottom (of what is left of heap) trickledown()
50 45 40 40 40 50 45 50 45 50 45 40 55 60 55 60 55 60 55 60 75 75 75 75 Remove biggest and insert at bottom (of what is left of heap) trickledown() Remove biggest and insert at bottom (of what is left of heap) No trickledown() needed