Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2018
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.65 KB | None | 0 0
  1. class EmptyHeapException(Exception):
  2. pass
  3. class Heap():
  4. ''' represents a heap, which is a complete binary tree, and satisfies
  5. a heap-order, using a list.
  6. In this implelmentation, each node contains the keys only.
  7. you complete this code by storing an entry (key, value) in each node.
  8. '''
  9. def __init__(self, root_data):
  10. '''(eah, obj) -> NoneType
  11. construct a heap with data as its root'''
  12. #representation invariant
  13. # _heap is a list
  14. # _heap[0] represents the root of the tree
  15. # _heap[0] has the highest priority
  16. # _heap[2*i + 1] represents the left child of the
  17. # node that stored at index i, and _heap[2*i + 1] >= _heap[i]
  18. # _heap[2*i + 2] represents the right child of the
  19. # node that stored at index i, and _heap[2*i + 2] >= _heap[i]
  20. # _heap[len(_heap) -1] shows the last node
  21. # _heap[:] represents the result of traversing the tree by BFS, if not empty
  22.  
  23.  
  24. # append root_data to a newly created empty list.
  25. self._heap = []
  26. self._heap.append(root_data)
  27.  
  28. def size(self):
  29. '''(Heap) -> int
  30. returns the number of nodes in the heap'''
  31. return len(self._heap)
  32.  
  33. def is_empty(self):
  34. '''(Heap) -> bool
  35. returns True if this heap is empty'''
  36. return len(self._heap) == 0
  37.  
  38. def remove_last_node(self):
  39. '''(Heap) -> obj
  40. removes the last node from the heap and returns the key stored in this node
  41. Raises: EmptyHeapException if this heap is empty'''
  42. if (self.is_empty()):
  43. raise EmptyHeapException("Heap is empty")
  44. return self._heap.pop(len(self._heap)-1)
  45.  
  46. def min(self):
  47. '''(Heap) -> obj
  48. returns the item with the highest priority
  49. Raises: EmptyHeapException'''
  50. if (self.is_empty()):
  51. raise EmptyHeapException("Heap is empty")
  52. return self._heap[0]
  53.  
  54. def insert(self, data):
  55. '''(Heap, obj) -> NoenType
  56. insert the given data at right place in the heap'''
  57. # step 1, 2, 3: find the new last node, insert data, update last node
  58. # new last node is the element at len(self._heap)
  59. self._heap.append(data)
  60. #step 3, restore heap-order
  61. self.upheap_bubbling()
  62. def upheap_bubbling (self):
  63. '''(Heap) -> None
  64. restores heap order by swaping the items along an upward path from inserted node'''
  65. # find the last node index
  66. cur = len(self._heap)-1
  67. # find the parent (always (last_node - 1//2) because it rounded down)
  68. parent = (cur -1 )//2
  69. # continue swapping until last node in right place or you get to the root
  70. while (cur > 0 and self._heap[parent] > self._heap[cur]):
  71. self._heap[parent] , self._heap[cur] = self._heap[cur] , self._heap[parent]
  72. # update cur and parent
  73. cur = parent
  74. parent = (cur -1 )//2
  75.  
  76. def extract_min(self):
  77. '''(Heap) -> obj
  78. removes the highest priority item and return it.
  79. Raises: EmptyHeapException
  80. '''
  81. # raise an exception if heap is empty
  82. if (self.is_empty()):
  83. raise EmptyHeapException ("Heap is empty")
  84. # step 1: get the min value
  85. min_value = self._heap[0]
  86. # remove the last node
  87. l_node = self._heap.pop(len(self._heap) -1)
  88. # step2: replace the root with last node if at least there is one item in the heap
  89. if(len(self._heap) != 0):
  90. # replace root with the last node
  91. self._heap[0] = l_node
  92. # step 3, 4: last node will be updated automatically, so restore the heap_order
  93. self.downheap_bubbling()
  94. # return the highest priority item
  95. return min_value
  96.  
  97. def downheap_bubbling(self):
  98. '''(Heap) -> NoneType
  99. restore the heap order by swapping the items down the path'''
  100. # start from the root
  101. cur = 0
  102. # continue going down while heap order is violated
  103. while (self.violates(cur)):
  104. # find the index of the child which contains smaller data/ violates heap order
  105. child_index = self.find_index(cur)
  106. # swap data at cur and data at child
  107. self._heap[cur] , self._heap[child_index] = self._heap[child_index] , self._heap[cur]
  108. # update cur to point to child_index
  109. cur = child_index
  110. def violates(self, index):
  111. '''(Heap, index) -> bool
  112. checks if the given index has a key greater than one of its children'''
  113. # get left and right child index
  114. left = index * 2 + 1
  115. right = index * 2 + 2
  116. # raise a flag as an indicator of the violation
  117. violates = True
  118. # if cur index points to a leaf, it does not violate the heap order. a leaf is a node whose left child index is greater than the heap's length
  119. if (left >= len(self._heap)):
  120. violates = False
  121. # otherwise, it may have one child. since the heap is a complete tree, therfore it has a left child, which means the index to right child is >= than the heap's length. In this case we check the left child for the violation of heap-order
  122. elif (right >= len(self._heap)):
  123. violates = self._heap[index] > self._heap[left]
  124. #otherwise, it has two children, therefore you need to check both the children
  125. else:
  126. violates = (self._heap[index] > self._heap[left]) or (self._heap[index] > self._heap[right])
  127. return violates
  128. def find_index(self, index):
  129. '''(Heap, int) -> int
  130. return the index where it violates the heap order'''
  131. # find left and right child and initialize returned index
  132. left = index * 2 + 1
  133. right = index * 2 + 2
  134. returned_index = 0
  135. #if it has one child, it is left child. which means right child's index >= len of heap
  136. if (right >= len (self._heap)):
  137. returned_index = left
  138. # otherwise, we should find which one of its children has smaller data
  139. elif (self._heap[left] < self._heap[right]):
  140. returned_index = left
  141. else:
  142. returned_index = right
  143. #return the found index
  144. return returned_index
  145.  
  146. def BFS(self):
  147. '''(BT) -> str
  148. traverse the tree in Breadth First search mehtod
  149. '''
  150. # remove all Nones from the list
  151. result = ""
  152. for item in self._heap:
  153. if (item is not None):
  154. result = result + " " + str(item)
  155. return result
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement