|
| 1 | +{ |
| 2 | + "cells": [ |
| 3 | + { |
| 4 | + "cell_type": "markdown", |
| 5 | + "metadata": {}, |
| 6 | + "source": [ |
| 7 | + "#### Author: OMKAR PATHAK" |
| 8 | + ] |
| 9 | + }, |
| 10 | + { |
| 11 | + "cell_type": "markdown", |
| 12 | + "metadata": {}, |
| 13 | + "source": [ |
| 14 | + "# Heap" |
| 15 | + ] |
| 16 | + }, |
| 17 | + { |
| 18 | + "cell_type": "markdown", |
| 19 | + "metadata": {}, |
| 20 | + "source": [ |
| 21 | + "A Binary Heap is a Binary Tree with following properties.\n", |
| 22 | + "* It’s a complete tree (All levels are completely filled except possibly the last level and the last level has all keys as left as possible). This property of Binary Heap makes them suitable to be stored in an array.\n", |
| 23 | + "* A Binary Heap is either Min Heap or Max Heap. In a Min Binary Heap, the key at root must be minimum among all keys present in Binary Heap. The same property must be recursively true for all nodes in Binary Tree. Max Binary Heap is similar to Min Heap." |
| 24 | + ] |
| 25 | + }, |
| 26 | + { |
| 27 | + "cell_type": "markdown", |
| 28 | + "metadata": {}, |
| 29 | + "source": [ |
| 30 | + "### Properties of Heap:" |
| 31 | + ] |
| 32 | + }, |
| 33 | + { |
| 34 | + "cell_type": "markdown", |
| 35 | + "metadata": {}, |
| 36 | + "source": [ |
| 37 | + "* The root is the second item in the array. We skip the index zero cell of the array for the convenience of implementation. Consider **k-th** element of the array, the\n", |
| 38 | + "- its left child is located at 2*k index \n", |
| 39 | + "- its right child is located at 2*k+1. index \n", |
| 40 | + "- its parent is located at k/2 index" |
| 41 | + ] |
| 42 | + }, |
| 43 | + { |
| 44 | + "cell_type": "markdown", |
| 45 | + "metadata": {}, |
| 46 | + "source": [ |
| 47 | + "### Applications" |
| 48 | + ] |
| 49 | + }, |
| 50 | + { |
| 51 | + "cell_type": "markdown", |
| 52 | + "metadata": {}, |
| 53 | + "source": [ |
| 54 | + "Applications of Heaps: <br>\n", |
| 55 | + "1) Heap Sort: Heap Sort uses Binary Heap to sort an array in O(nLogn) time.\n", |
| 56 | + "\n", |
| 57 | + "2) Priority Queue: Priority queues can be efficiently implemented using Binary Heap because it supports insert(), delete() and extractmax(), decreaseKey() operations in O(logn) time. Binomoial Heap and Fibonacci Heap are variations of Binary Heap. These variations perform union also efficiently.\n", |
| 58 | + "\n", |
| 59 | + "3) Graph Algorithms: The priority queues are especially used in Graph Algorithms like Dijkstra’s Shortest Path and Prim’s Minimum Spanning Tree.\n", |
| 60 | + "\n", |
| 61 | + "4) Many problems can be efficiently solved using Heaps. See following for example.\n", |
| 62 | + " * K’th Largest Element in an array\n", |
| 63 | + " * Sort an almost sorted array\n", |
| 64 | + " * Merge K Sorted Arrays" |
| 65 | + ] |
| 66 | + }, |
| 67 | + { |
| 68 | + "cell_type": "markdown", |
| 69 | + "metadata": {}, |
| 70 | + "source": [ |
| 71 | + "### So why is Binary Heap Preferred for Priority Queue?" |
| 72 | + ] |
| 73 | + }, |
| 74 | + { |
| 75 | + "cell_type": "markdown", |
| 76 | + "metadata": {}, |
| 77 | + "source": [ |
| 78 | + "* Since Binary Heap is implemented using arrays, there is always better locality of reference and operations are more cache friendly.\n", |
| 79 | + "* Although operations are of same time complexity, constants in Binary Search Tree are higher.\n", |
| 80 | + "* We can build a Binary Heap in O(n) time. Self Balancing BSTs require O(nLogn) time to construct.\n", |
| 81 | + "* Binary Heap doesn’t require extra space for pointers.\n", |
| 82 | + "* Binary Heap is easier to implement.\n", |
| 83 | + "* There are variations of Binary Heap like Fibonacci Heap that can support insert and decrease-key in ?(1) time" |
| 84 | + ] |
| 85 | + }, |
| 86 | + { |
| 87 | + "cell_type": "markdown", |
| 88 | + "metadata": {}, |
| 89 | + "source": [ |
| 90 | + "### Implementing Min-Heap in Python:" |
| 91 | + ] |
| 92 | + }, |
| 93 | + { |
| 94 | + "cell_type": "code", |
| 95 | + "execution_count": 13, |
| 96 | + "metadata": {}, |
| 97 | + "outputs": [ |
| 98 | + { |
| 99 | + "name": "stdout", |
| 100 | + "output_type": "stream", |
| 101 | + "text": [ |
| 102 | + "Deleted: 2\n", |
| 103 | + "Deleted: 3\n", |
| 104 | + "Deleted: 5\n", |
| 105 | + "Deleted: 3\n" |
| 106 | + ] |
| 107 | + } |
| 108 | + ], |
| 109 | + "source": [ |
| 110 | + "# Author: OMKAR PATHAK\n", |
| 111 | + "\n", |
| 112 | + "class BinaryHeap(object):\n", |
| 113 | + " def __init__(self):\n", |
| 114 | + " self.heap = [0]\n", |
| 115 | + " self.currentSize = 0\n", |
| 116 | + "\n", |
| 117 | + " # for shifting the node up\n", |
| 118 | + " def shiftUp(self, index):\n", |
| 119 | + " while (index // 2) > 0:\n", |
| 120 | + " if self.heap[index] < self.heap[index // 2]: # (currentSize // 2) is the parent \n", |
| 121 | + " temp = self.heap[index // 2]\n", |
| 122 | + " self.heap[index // 2] = self.heap[index]\n", |
| 123 | + " self.heap[index] = temp\n", |
| 124 | + " index = index // 2\n", |
| 125 | + "\n", |
| 126 | + " # to insert a node in the heap\n", |
| 127 | + " def insert(self, key):\n", |
| 128 | + " self.heap.append(key)\n", |
| 129 | + " self.currentSize += 1\n", |
| 130 | + " self.shiftUp(self.currentSize)\n", |
| 131 | + "\n", |
| 132 | + " # for shifting down a node\n", |
| 133 | + " def shiftDown(self, index):\n", |
| 134 | + " while(index * 2) <= self.currentSize:\n", |
| 135 | + " minimumChild = self.minChild(index)\n", |
| 136 | + " if self.heap[index] > self.heap[minimumChild]:\n", |
| 137 | + " temp = self.heap[index]\n", |
| 138 | + " self.heap[index] = self.heap[minimumChild]\n", |
| 139 | + " self.heap[minimumChild] = temp\n", |
| 140 | + " index = minimumChild\n", |
| 141 | + " \n", |
| 142 | + " # for finding the child with minimum value\n", |
| 143 | + " def minChild(self,i):\n", |
| 144 | + " if i * 2 + 1 > self.currentSize:\n", |
| 145 | + " return i * 2\n", |
| 146 | + " else:\n", |
| 147 | + " if self.heap[i * 2] < self.heap[i * 2 + 1]:\n", |
| 148 | + " return i * 2\n", |
| 149 | + " else:\n", |
| 150 | + " return i * 2 + 1\n", |
| 151 | + " \n", |
| 152 | + " # for deleting a node from the heap and maintaining the heap property\n", |
| 153 | + " def delete(self):\n", |
| 154 | + " deletedNode = self.heap[1]\n", |
| 155 | + " self.heap[1] = self.heap[self.currentSize]\n", |
| 156 | + " self.currentSize -= 1\n", |
| 157 | + " self.heap.pop()\n", |
| 158 | + " self.shiftDown(1)\n", |
| 159 | + " return deletedNode\n", |
| 160 | + " \n", |
| 161 | + " # for building heap\n", |
| 162 | + " def buildHeap(self, alist):\n", |
| 163 | + " i = len(alist) // 2\n", |
| 164 | + " self.currentSize = len(alist)\n", |
| 165 | + " self.heap = [0] + alist[:]\n", |
| 166 | + " while (i > 0):\n", |
| 167 | + " self.shiftDown(i)\n", |
| 168 | + " i = i - 1\n", |
| 169 | + " \n", |
| 170 | + "bh = BinaryHeap()\n", |
| 171 | + "bh.buildHeap([9,5,6,2,3])\n", |
| 172 | + "\n", |
| 173 | + "print('Deleted:',bh.delete())\n", |
| 174 | + "print('Deleted:',bh.delete())\n", |
| 175 | + "print('Deleted:',bh.delete())\n", |
| 176 | + "bh.insert(3)\n", |
| 177 | + "print('Deleted:',bh.delete())" |
| 178 | + ] |
| 179 | + } |
| 180 | + ], |
| 181 | + "metadata": { |
| 182 | + "kernelspec": { |
| 183 | + "display_name": "Python 3", |
| 184 | + "language": "python", |
| 185 | + "name": "python3" |
| 186 | + }, |
| 187 | + "language_info": { |
| 188 | + "codemirror_mode": { |
| 189 | + "name": "ipython", |
| 190 | + "version": 3 |
| 191 | + }, |
| 192 | + "file_extension": ".py", |
| 193 | + "mimetype": "text/x-python", |
| 194 | + "name": "python", |
| 195 | + "nbconvert_exporter": "python", |
| 196 | + "pygments_lexer": "ipython3", |
| 197 | + "version": "3.5.2" |
| 198 | + } |
| 199 | + }, |
| 200 | + "nbformat": 4, |
| 201 | + "nbformat_minor": 2 |
| 202 | +} |
0 commit comments