9. Heaps

The word heap is used in a couple of different contexts in Computer Science. A heap sometimes refers to an area of memory used for dynamic (i.e. run-time) memory allocation. Another meaning, and the topic of this chapter, is a data structure that is conceptually a complete binary tree. Heaps are used in implementing priority queues, the heapsort algorithm, and some graph algorithms. Heaps are somewhat like binary search trees in that they maintain an ordering of the items within the tree. However, a heap does not maintain a complete ordering of its items. This has some implications for how a heap may be used.

9.1. Heap Program

Here you can download a starter shell for the heap implementation described in the chapter. To run this program you must also download the person.py file. Place both modules in the same directory. The heap.py program file contains a main function to test your heap implementation.

This heap program can be modified to support a different number of children. For instance, a four child heap is also possible. The file defaults to a three child heap.

  1
  2'''
  3  File:  heap.py
  4  Author: 
  5  Date:
  6  Description:  This module provides the class Heap.  We can create heaps which
  7     are either largest-on-top or smallest-on-top.  We can also create heaps 
  8     with a maximum number of children of our choice.  As written, the default
  9     number of children is 3 and the default initial capacity is 5.  These
 10     parameters can be changed by the way we invoke the class constructor.
 11     
 12     The module also provides the efficient heap sort method.  By default, the
 13     methods sorts objects in increasing order.  But we can also sort objects
 14     in decreasing order.
 15     
 16     Our implementation works for objects of any class that understand the
 17     relational operators.
 18
 19'''
 20
 21testing = False
 22from person import Person
 23import math
 24
 25def heapSort(aSequence, increasingOrder = True):
 26  '''  This method will answer a list of the elements of aSequence, which
 27   by default will be sorted in increasing order.  To sort in decreasing
 28   order, send a second parameter which is False.
 29  '''
 30  # Do last, after buildFrom() and siftDownFrom(), other methods.
 31  # More code needed!
 32  return h.data[:]
 33
 34
 35class Heap:
 36  '''
 37  The class Heap provides a generic heap abstract data type.
 38  The instances of this class can hold objects of any sort that
 39  understand the relational operators.  It also allows us to create
 40  heaps with any maximum number of children.
 41  '''
 42
 43  DefaultCapacity = 5           #  A class variable
 44  DefaultNumberOfChildren = 3   #  Another class variable
 45
 46  def __init__(self, capacity = DefaultCapacity,
 47          largestOnTop = True, numberOfChildren =
 48              DefaultNumberOfChildren):
 49    self.size = 0
 50    self.capacity = capacity
 51    self.largestOnTop = largestOnTop
 52    self.data = [None]*capacity
 53    self.maxChildren = numberOfChildren
 54
 55  def __str__(self):
 56    if self.largestOnTop:
 57       sortOfHeap = 'largest on top'
 58    else:
 59       sortOfHeap = 'smallest on top'
 60    st = 'It is a ' + sortOfHeap + ' heap:\n'
 61    #  .......
 62    return st
 63
 64  def addToHeap(self,newObject):
 65    '''If the heap is full, double its current capacity.
 66       Add the newObject to the heap, maintaining it as a
 67       heap of the same type.  Answer newObject.
 68    '''
 69    pass  # Allows compilation of file.  Replace with actual code.
 70
 71  def bestChildOf(self, index, lastIndex):
 72    ''' Answer the index of the "best child" of self.data[index], if it
 73      exists. If not, answer None.  lastIndex is the index of the last 
 74      object in the heap.  For a largest on top heap, the best child is the
 75      largest child.  For a smallest on top heap, it is the smallest child
 76      of the node with the given index.
 77    '''
 78    bestChild = None
 79    #  .......
 80    return bestChild
 81            
 82  def buildFrom(self, aSequence):
 83    '''aSequence is an instance of a sequence collection which
 84        understands the comparison operators. The elements of
 85        aSequence are copied into the heap and ordered to build
 86        a heap. '''
 87    pass
 88
 89  def removeTop(self):
 90    '''  If the heap is not empty, remove the top element
 91      of the heap and adjust the heap accordingly.  Answer the object
 92      removed.  If the heap is empty, return None.
 93    '''
 94    pass
 95
 96  def siftDownFrom( self, fromIndex ):
 97    '''fromIndex is the index of an element in the heap.
 98      Pre: data[fromIndex..size-1] satisfies the heap condition,
 99      except perhaps for the element self.data[fromIndex].
100      Post:  That element is sifted down as far as neccessary to
101      maintain the heap structure for data[fromIndex..size-1].
102    '''
103    pass
104
105  def __siftUpFrom(self, child):
106    ''' child is the index of a node in the heap.  This method sifts
107      that node up as far as necessary to ensure that the path to the root
108      satisfies the heap condition. '''
109    pass
110
111  def __siftDownFromTo(self, fromIndex, lastIndex):
112    '''fromIndex is the index of an element in the heap.
113      Pre: data[fromIndex..lastIndex] satisfies the heap condition,
114      except perhaps for the element data[fromIndex].
115      Post:  That element is sifted down as far as neccessary to
116      maintain the heap structure for data[fromIndex..lastIndex].'''
117    pass
118    
119  def levelByLevelString(self):
120    ''' Return a string which lists the contents of the heap
121       level by level.
122    '''
123    index = 0 # start at the root node
124    maxLevel = \
125       math.ceil(math.log(self.size*(self.numberOfChildren - 1) + 1)/
126            math.log(self.numberOfChildren))
127    #  MORE!              
128
129  #  Other methods?
130  #  Use Doc strings for all methods!
131        
132def main():
133  print("My name is ")
134  h = Heap()
135  h.addToHeap(20)
136  h.addToHeap(40)
137  h.addToHeap(-10)
138  h.addToHeap(72)
139  h.addToHeap(84)
140  h.addToHeap(-100)
141  h.addToHeap(54)
142  h.addToHeap(66)
143  h.addToHeap(99)
144  h.addToHeap(1000)
145  h.addToHeap(900)
146  print(h)
147
148  h.data[0] = 50
149  h.siftDownFrom(0)
150  print(h)
151
152  h.data[0] = 60
153  h.siftDownFrom(0)
154  print(h)
155
156  h = Heap(3, False)
157  h.buildFrom((20,40,-10, 72, 84, -100, 54,66, 99))
158  print(h)
159
160  theList = heapSort([10, 30, -100, 50, 20, 30, -40,70, 5, 50])
161  print(theList)
162
163  theList = heapSort([10, 30, -100, 50, 20, 30, -40,70, 5, 50], False)
164  print(theList)
165
166  print( "\nThe following is the extra output that happens when we" )
167  print( " create a heap that can have 5 children per node. \n" )
168  heap = Heap(numberOfChildren = 5)
169  heap.buildFrom((10, 20, -29, 16, 70, 30, 20, 100, 38, -293, \
170   77, -19, -77, 230, 91, -230, -48, 23))
171  print(heap)
172
173  a = heapSort((10, 20, -29, 16, 70, 30, 20, 100, 38, -293, \
174   77, -19, -77, 230, 91, -230, -48, 23))
175  print(a)
176
177
178  #  Extra stuff to test removeTop()
179  h = Heap()
180  h.addToHeap(20)
181  h.addToHeap(40)
182  h.addToHeap(-10)
183  h.addToHeap(72)
184  h.addToHeap(84)
185  h.addToHeap(-100)
186  h.addToHeap(54)
187  h.addToHeap(66)
188  h.addToHeap(99)
189  h.addToHeap(1000)
190  h.addToHeap(900)
191  print(h)
192
193  print(h.removeTop())
194  print(h)
195
196  print( "trying heapSort method:" )
197  print( heapSort((20, -30, 45, 921, 37, 200, -1000, 4000, 57)) )
198  print(  heapSort((20, -30, 45, 921, 37, 200, -1000, 4000, 57), False))
199  joe = Person('Joe', 99)
200  jill = Person('Jill', 200)
201  walt = Person('Walter', 3000)
202  dave = Person('David', 23)
203  kent = Person('Kent', 220)
204  alan = Person('Al', 110)
205  folks = [joe, jill, walt, dave, kent, alan]
206  print( heapSort(folks) )
207  print( heapSort(folks, False ))
208
209  h = Heap()
210  h.addToHeap(20)
211  h.addToHeap(40)
212  h.addToHeap(-10)
213  h.addToHeap(72)
214  h.addToHeap(84)
215  h.addToHeap(-100)
216  h.addToHeap(54)
217  h.addToHeap(66)
218  h.addToHeap(99)
219  h.addToHeap(1000)
220  h.addToHeap(900)
221  print()
222  print( 'A level by level listing of the heap:' )
223  print( h.levelByLevelString() )
224
225
226if __name__ == '__main__': main()
227
228'''  The following is the output from running this code:
229My name is YOUR NAME
230[evaluate heap.py]
231It is a largest on top heap:
232The size of the heap is 11.
233The capacity of the heap is 20.
234The elements of the heap are: 
2351000
23672
23799
238900
23920
240-100
24154
242-10
24366
24484
24540
246
247It is a largest on top heap:
248The size of the heap is 11.
249The capacity of the heap is 20.
250The elements of the heap are: 
251900
25272
25399
25450
25520
256-100
25754
258-10
25966
26084
26140
262
263It is a largest on top heap:
264The size of the heap is 11.
265The capacity of the heap is 20.
266The elements of the heap are: 
26799
26872
26984
27050
27120
272-100
27354
274-10
27566
27660
27740
278
279Output from buildFrom():
280It is a smallest on top heap:
281The size of the heap is 9.
282The capacity of the heap is 9.
283The elements of the heap are: 
284-100
28520
286-10
28772
28884
28940
29054
29166
29299
293
294[-100, -40, 5, 10, 20, 30, 30, 50, 50, 70]
295[70, 50, 50, 30, 30, 20, 10, 5, -40, -100]
296
297The following is the extra output that happens when we
298 create a heap that can have 5 children per node. 
299
300It is a largest on top heap:
301The size of the heap is 18.
302The capacity of the heap is 18.
303The elements of the heap are: 
304230
305100
30691
30723
30870
30930
31020
31120
31238
313-293
31477
315-19
316-77
317-29
31810
319-230
320-48
32116
322
323[-293, -230, -77, -48, -29, -19, 10, 16, 20, 20, 23, 30, 38, 70, 77, 91, 100, 230]
324It is a largest on top heap:
325The size of the heap is 11.
326The capacity of the heap is 20.
327The elements of the heap are: 
3281000
32972
33099
331900
33220
333-100
33454
335-10
33666
33784
33840
339
340Output from removeTop():
3411000
342It is a largest on top heap:
343The size of the heap is 10.
344The capacity of the heap is 20.
345The elements of the heap are: 
346900
34772
34899
34940
35020
351-100
35254
353-10
35466
35584
356
357trying heapSort method:
358[-1000, -30, 20, 37, 45, 57, 200, 921, 4000]
359[4000, 921, 200, 57, 45, 37, 20, -30, -1000]
360[Name: David Id: 23 , Name: Joe Id: 99 , Name: Al Id: 110 ,
361   Name: Jill Id: 200 , Name: Kent Id: 220 , Name: Walter Id: 3000 ]
362[Name: Walter Id: 3000 , Name: Kent Id: 220 , Name: Jill Id: 200 , 
363   Name: Al Id: 110 , Name: Joe Id: 99 , Name: David Id: 23 ]
364
365A level by level listing of the heap:
366Level 1:
3671000
368
369Level 2:
37072
37199
372900
373
374Level 3:
37520
376-100
37754
378-10
37966
38084
38140
382
383'''

9.2. Figures from Text

../_images/heap1.png

Fig. 1: Heap Shape

../_images/heap2.png

Fig. 2: Sample Heap

../_images/heap3.png

Fig. 3: Heap Organization

../_images/heap4.png

Fig. 4: Building a Heap Part One

../_images/heap5.png

Fig. 5: Building a Heap Part Two

../_images/heap6.png

Fig. 6: Building a Heap Part Three

../_images/heap7.png

Fig. 7: Adding 98 to the Heap

../_images/heap8.png

Fig. 8: Conceptual View While Adding 98 to the Heap

../_images/heap9.png

Fig. 9: Heap After Moving 98 to Correct Location

../_images/heap10.png

Fig. 10: A Perfect Binary Tree

../_images/logplot.png

Fig. 11: Plot of log(n)

../_images/heap11.png

Fig. 12: Just Before Phase II

../_images/heap12.png

Fig. 13: After Swapping First and Last Values

../_images/heap13.png

Fig. 14: After the First Pass of Phase II

../_images/heap14.png

Fig. 15: After the Second Pass of Phase II

../_images/heap15.png

Fig. 16: After the Third Pass of Phase II

../_images/heap16.png

Fig. 17: After the Fourth and Final Pass of Phase II

../_images/heap17.png

Fig. 18: A List to be Heapsorted

../_images/heap18.png

Fig. 19: After Forming a Sub-Heap

../_images/heap19.png

Fig. 20: After Forming a Second Sub-Heap

../_images/heap20.png

Fig. 21: Sifting the 15 Down

../_images/heap21.png

Fig. 22: The Final Heap using Version 2 of Phase I

../_images/heap22.png

Fig. 23: A Binary Heap of Height 4

../_images/timinggraph.png

Fig. 24: Comparison of Several Sorting Algorithms