diff --git a/.gitignore b/.gitignore index 2cceedb..96d9c40 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ **/__pycache__/* +*.pyc diff --git a/Data Structure/Heap/README.md b/Data Structure/Heap/README.md new file mode 100644 index 0000000..f825951 --- /dev/null +++ b/Data Structure/Heap/README.md @@ -0,0 +1,33 @@ +# Heap + +A **Heap** is a tree based data structure and it is a complete binary tree which satisfies the heap ordering property. The ordering can be one of two types: + +the **min-heap property:** the value of each node is greater than or equal to the value of its parent, with the minimum-value element at the root. + +the **max-heap property:** the value of each node is less than or equal to the value of its parent, with the maximum-value element at the root. + +![heap](max_heap_deletion_animation.gif) + +**Basic Operations:** + +Following are the basic operations supported by a list. + +* **Insertion** − Adds an element at the max heap. + +* **Deletion** − Deletes an element at the beginning of the heap. + +* **Display** − Displays the complete heap. + +* **Max** − Get the max element from the heap. + + +#### Complexity Analysis +- Space - O(n) +- Search - O(n) +- Insertion - O(1) +- Delete - O(log n) (Deletion from beginning) +- Peek - O(1) +### More on this topic +- https://en.wikipedia.org/wiki/Heap_(data_structure) +- https://www.hackerearth.com/practice/data-structures/trees/heapspriority-queues/tutorial/ +- https://www.geeksforgeeks.org/binary-heap/ diff --git a/Data Structure/Heap/heap.py b/Data Structure/Heap/heap.py new file mode 100644 index 0000000..7c1e4fb --- /dev/null +++ b/Data Structure/Heap/heap.py @@ -0,0 +1,54 @@ +"""MaxHeap implementation using python""" + + +class MaxHeap(object): + + def __init__(self, maxSize=None): + self.heap = [] + self.HEAP_SIZE = maxSize + + def _swap(self,i,j): + self.heap[i], self.heap[j] = self.heap[j], self.heap[i] + + def _heapIsFull(self): + return (self.HEAP_SIZE != None and len(self.heap) >= self.HEAP_SIZE) + + def insert(self, item): + if self._heapIsFull(): + "Heap is full..." + else: + self.heap.append(item) + # adjust parent node item + self._bubbleUp(len(self.heap)-1) + + def _bubbleUp(self, currentPosition): + if currentPosition >= 1: # no need to do bubbleUp for 1 element + index = currentPosition + parentIndex = (index-1)//2 + + if parentIndex >= 0 and self.heap[parentIndex] < self.heap[index]: + self._swap(parentIndex, index) + self._bubbleUp(parentIndex) + + def peek(self): + return self.heap[0] if self.heap else None + + def pop(self): + element = self.peek() + if element: + self._swap(0, len(self.heap) - 1) + self.heap.pop() + self._bubbleDown(0) + return element + + def _bubbleDown(self, index): + leftChildIndex = 2 * index + 1 + rightChildIndex = 2 * index + 2 + largest = index + if len(self.heap) > leftChildIndex and self.heap[largest] < self.heap[leftChildIndex]: + largest = leftChildIndex + if len(self.heap) > rightChildIndex and self.heap[largest] < self.heap[rightChildIndex]: + largest = rightChildIndex + if largest!=index: + self._swap(index, largest) + self._bubbleDown(largest) diff --git a/Data Structure/Heap/max_heap_deletion_animation.gif b/Data Structure/Heap/max_heap_deletion_animation.gif new file mode 100644 index 0000000..3dc54d3 Binary files /dev/null and b/Data Structure/Heap/max_heap_deletion_animation.gif differ diff --git a/Data Structure/Heap/test_heap.py b/Data Structure/Heap/test_heap.py new file mode 100644 index 0000000..30ba788 --- /dev/null +++ b/Data Structure/Heap/test_heap.py @@ -0,0 +1,29 @@ +import unittest +from heap import MaxHeap + +class MaxHeapTestCase(unittest.TestCase): + """ Test for Heap.py""" + def test(self): + # test data + ob = MaxHeap() + ob.insert(10) + ob.insert(5) + ob.insert(6) + ob.insert(3) + ob.insert(8) + ob.insert(20) + self.assertEqual(ob.peek(), 20, msg="Max Element is not matched") + ob.pop() + ob.pop() + self.assertEqual(ob.peek(), 8, msg="Max Element is not matched") + ob.pop() + self.assertEqual(ob.peek(), 6, msg="Max Element is not matched") + ob.pop() + ob.pop() + ob.pop() + self.assertEqual(ob.peek(), None, msg="Max Element is not matched") + +if __name__ == '__main__': + unittest.main() + +