CS201 - Spring 2014 - Class 27

  • look at ArrayListPriorityQueue class in PriorityQueue code

  • heapify
       - called on a node (in the code, this is specified by providing the index of that node)
       - assumes both children of that node are valid heaps (or null)
       - HOWEVER, the current node/subtree is not a heap
       - turns the subtree at the current node into a heap
          - recursively moves the current value down

  • Building a heap: given n data items, how can we build a heap?
       - the easy version:
          - call add n times
          - what is the run-time?
             - n calls to add
             - each call to add is O(log n)
             - O(n log n)
       - can we use our heapify method?
          - heapify requires that the left and right children are valid heaps
          - Any way to accomplish this easily?
             - single element heaps are trivially valid heaps
          - basic idea:
             - start with n/2 single element heaps
             - slowly build up bigger and bigger heaps
             - for example:
                - let's say we want to build a heap from 1-7 in some random order, say:
                   - 1, 5, 6, 3, 4, 2, 7
                - what does this look like as a heap/tree?
                - is it a valid heap? No!
                - are any of the sub-tree/sub-heaps valid heaps?
                   - all of the leaves are!
                - Does this help us (think heapify)?
                   - call heapify on all of the nodes above the leaves
                   - repeat!
             - look at constructor in ArrayListPriorityQueue class in PriorityQueue code
                - we let the end n/2 elements in the data item be the single element heaps
                - work our way from n/2 to the front of the data
                - since we know that everything with an index > than the current index is a valid heap, each call to heapify will generate a valid heap
          - run-time?
             - n/2 calls to heapify
             - easy answer is O(n log n), since each call to heapify is O(log n)
             - however, a lot of the early calls to heapify are not O(log n), for example the first n/4 calls are just O(1) since there is at most one swap that can happen
             - with a little bit of math, you can show that it actually is O(n) to construct a heap using this approach (follow the line of reasoning above and you'll get: \sum_i=1^(log n) (n i)/(2^(i+1)), which works out to O(n)

  • could we use a heap to sort data?
       - build a heap with our data
       - call extractMin n times
       - what is the runtime?
          - O(n) to build the heap
          - n calls to extractMin = O(n log n)
          - O(n log n) overall
       - this is called heap-sort and is another O(n log n) time algorithm for sorting data

  • can we do better than O(n log n) for sorting?

  • binary heaps in summary
       - binary heaps allow us to insert and extract the minimum values in O(log n) time
       - http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html