CS201 - Spring 2014 - Class 26

  • classes without constructors
       - if you write a class without a constructor java will generate a zero-parameter one for you
       - any instance variable that you've initialized with = will get that value
       - any that don't have an initialization will get their "default" value

  • heaps
       - a heap is a binary tree where:
          - min heap:
             - the value of a parent is less than or equal to the value of its children
          - max heap:
             - the value of a parent is greater than or equal to the value of its children
          - a full binary tree except the leaves are filled in from left to right
       - draw a binary heap:
          - [16], [8, 10], [3, 7, 9, 5] [2, 4, 1]
       - A few other observations about binary heaps...
          - min heap:
             - the smallest value in a heap is the root node
          - max heap:
             - the largest value in a heap is the root node
          - like binary trees, all nodes in a heap are themselves heaps
          - level does NOT indicate size

  • representing a heap
       - we could store the heap using references as we have with other binary trees
       - we can also store it using an array (or ArrayList) by leveraging the fact that it is a complete tree
          left(i) = 2i + 1
          right(i) = 2i + 2
          parent(i) = floor((i-1)/2)
       - for example, the tree above would be:
          [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
       - what is the left child of 10?
          - index 2*2+1 = 5, or the value 9
       - what is the parent of value 2?
          - index (7-1)/2 = 3, or the value 8

  • which of the following are valid heaps?
       - [1, 2, 3, 4, 5, 6, 7, 8]
       - [3, 8, 9, 14, 11, 7, 10, 20, 17]
       - [1, 20, 2, 30, 25, 5, 6]
       - in tree form: [8]
       - in tree form: [1], [4, 8], [ , , 9, 13]

  • what are the advantages of array-based heaps/binary trees?
       - memory efficiency
       - can we do this with all binary trees?
          - yes
       - why don't we?
          - unless the tree is full or complete, there can be a large mount of wasted space

  • Adding items to a heap: given a valid heap, how do we add data?
       - could try and start at the top and then move our way down
          - this gets tricky if we try and maintain the complete tree
       - another idea:
          - add it to the bottom of the tree (maintaining the complete tree property)
          - propagate the value up the tree swapping with its parent until it's in the appropriate location
       - what is the worst-case run-time of this second approach?
          - O(height) = O(log n) since it's a complete tree

  • Getting the largest/smallest item from a heap: given a valid heap, how do we extract the minimum/maximum value?
       - we know that the minimum/maximum value is at the root
       - the challenge is that we need to remove it
       - one idea: remove it and then percolate the values up with the smallest child
          - as before, the challenge here is that it's easy to end up with something that isn't a complete tree
       - another idea:
          - similar to adding an element, we want to process at the end of the heap. Move the last element in the tree to the root position and then propagate the value down the tree until it's in the appropriate position
          - how do we do this?
             - starting at the root, compare the current node to the left and right child
             - if one of the children is smaller, swap the current value with the smallest child (it neither are, then we're done)
             - then, repeat this on the child heap that we just swapped with
       - what is the worst-case run-time?
          - O(height) = O(log n) since it's a complete tree