From e47e3241b89b7126a423f40e0f8e550f6055eac2 Mon Sep 17 00:00:00 2001
From: marina <138340846+bt3gl-cryptographer@users.noreply.github.com>
Date: Wed, 2 Aug 2023 12:01:57 -0700
Subject: [PATCH] add code for max and min heap
---
heaps/README.md | 213 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 198 insertions(+), 15 deletions(-)
diff --git a/heaps/README.md b/heaps/README.md
index c69cf7b..ecbc122 100644
--- a/heaps/README.md
+++ b/heaps/README.md
@@ -1,22 +1,205 @@
## heaps
-
-* a heap is a binary tree with two properties: it must have all of its nodes in a specific order and its shape must be complete (all the levels of the tree must be completely filled except maybe for the last one and the last level must have the left-most nodes filled, always).
-* a heap's root node must have all its children either greater than or equal to its children.
-* since you always remove the root, insertion and deletion takes O(log(n)).
-* duplicate values are allowed.
-* a **min heap** is a complete binary tree where each node is smaller than its children (the root is the min element). two key operations are:
- - insert: always by the element at the bottom, at the most rightmost post
- - extract_min: the minimum element is always on top, and removing it is the trickiest part:
- 1. remove and swap it with the last element (the bottom most rightmost)
- 2. the bubble down, swapping it with one of its children until the min-heap is properly restored (there is no order between right and left and it takes O(log n) time.
-* a heap could also be represented with a queue (array). in this case, the index of the parent node = [(n-1)/2].
-* a priority queue is a queue of data structures with some additional properties:
- 1. every item has a priority (usually an integer)
- 2. an item with a high priority is dequeued before an item with low priority
- 3. two items with an equal priority are dequeued based on their order in the queue
+
+
+
+
+
+
+
+
+* a heap is a binary tree with these properties:
+ * it must have all of **its nodes in a specific order**, and
+ * its shape must be **complete** (all the levels of the tree must be completely filled except maybe for the last one and the last level must have the left-most nodes filled, always).
+ * a max heap's **root node must** have all its children either **greater than or equal** to its children. a min heap is the opposite. duplicate values are allowed.
+
+* since you always remove the root, insertion and deletion takes `O(log(n))`. the maximum/minimum value in the heap can be obtained with `O(1)` time complexity.
+* heaps can be represented with linked lists or queues (arrays).
+ * in the case of arrays, the index of the parent `node = [(n-1)/2]`.
+
+
+----
+
+### priority queues
+
+* a priority queue is an abstract data type with the following properties:
+ 1. every item has a priority (usually an integer).
+ 2. an item with a high priority is dequeued before an item with low priority.
+ 3. two items with an equal priority are dequeued based on their order in the queue.
+* priority queues can be implemented with a stack, queue, or linked list data structures. however, heaps are the structure that guarantees both insertion and deletion to have time complexity `O(log N)` (while maintaining get_max/get_min at `O(1)`).
+
+---
+
+### min heaps
+
+* a **min heap** is a complete binary tree where each node is smaller than its children (the root is the min element).
+
+* `insert`:
+ - insert the element at the bottom, by finding the most rightmost node and checking its children: if left is empty, insert there, otherwise, insert on right.
+ - then compare this node to each parent, exchanging them until the tree's properties are corret.
+
+* `extract_min`:
+ - first, remove/return the top and then replace the tree's top with its latest element (the bottom most rightmost).
+ - then bubble down, swapping it with one of its children until the min-heap is properly restored
+ - there is no need for order between right and left, so this operation would only take `O(log n)` runtime.
+
+* the code below is an example:
+
+```python
+class MinHeap:
+
+ def __init__(self, size):
+
+ self.heapsize = size
+ self.minheap = [0] * (size + 1)
+ self.realsize = 0
+
+ def add(self, element):
+
+ if self.realsize + 1 > self.heapsize:
+ print("Too many elements!")
+ return False
+
+ self.realsize += 1
+ self.minheap[self.realsize] = element
+
+ index = self.realsize
+ parent = index // 2
+
+ while self.minheap[index] < self.minheap[parent] and index > 1:
+
+ self.minheap[parent], self.minheap[index] = self.minheap[index], self.minheap[parent]
+ index = parent
+ parent = index // 2
+
+ def peek(self):
+
+ return self.minheap[1]
+
+ def pop(self):
+
+ if self.realsize < 1:
+ print("Heap is empty.")
+ return False
+
+ else:
+ remove_element = self.minheap[1]
+ self.minheap[1] = self.minheap[self.realsize]
+ self.realsize -= 1
+ index = 1
+
+ while index <= self.realsize // 2:
+
+ left_children = index * 2
+ right_children = (index * 2) + 1
+
+ if self.minheap[index] > self.minheap[left_children] or \
+ self.minheap[index] > self.minheap[right_children]:
+
+ if self.minheap[left_children] < self.minheap[right_children]:
+
+ self.minheap[left_children], self.minheap[index] = self.minheap[index], self.minheap[left_children]
+ index = left_children
+
+ else:
+
+ self.minheap[right_children], self.minheap[index] = self.minheap[index], self.minheap[right_children]
+ index = right_children
+ else:
+ break
+
+ return remove_element
+
+ def size(self):
+ return self.realsize
+
+ def __str__(self):
+ return str(self.minheap[1 : self.realsize + 1])
+```
+
+
+
+---
+
+### max heaps
+
+* a **max heap** is a complete binary tree where each node is larger than its children (the root is the max element).
+
+* `insert`:
+ * insert the element at the bottom, at the leftmost node.
+ * then compare the node to each parent, exchanging them until the tree's properties are correct.
+
+* `extreact_max`:
+ * remove/return the top and then replace the tree's top with its bottom rightmost element.
+ * swap up until the max element is on the top.
+
+* the code below is an example:
+
+```python
+class MaxHeap:
+ def __init__(self, heapsize):
+
+ self.heapsize = heapsize
+ self.maxheap = [0] * (heapsize + 1)
+ self.realsize = 0
+
+ def add(self, element):
+
+ self.realsize += 1
+ if self.realsize > self.heapsize:
+ print("Too many elements!")
+ self.realsize -= 1
+ return False
+
+ self.maxheap[self.realsize] = element
+ index = self.realsize
+ parent = index // 2
+
+ while self.maxheap[index] > self.maxheap[parent] and index > 1:
+ self.maxheap[parent], self.maxheap[index] = self.maxheap[index], self.maxheap[parent]
+ index = parent
+ parent = index // 2
+
+ def peek(self):
+
+ return self.maxheap[1]
+
+ def pop(self):
+
+ if self.realsize < 1:
+ print("Heap is empty.")
+ return False
+ else:
+ remove_element = self.maxheap[1]
+ self.maxheap[1] = self.maxheap[self.realsize]
+ self.realsize -= 1
+ index = 1
+
+ while (index <= self.realsize // 2):
+
+ left_children = index * 2
+ right_children = (index * 2) + 1
+
+ if (self.maxheap[index] < self.maxheap[left_children] or self.maxheap[index] < self.maxheap[right_children]):
+ if self.maxheap[left_children] > self.maxheap[right_children]:
+ self.maxheap[left_children], self.maxheap[index] = self.maxheap[index], self.maxheap[left_children]
+ index = left_children
+ else:
+ self.maxheap[right_children], self.maxheap[index] = self.maxheap[index], self.maxheap[right_children]
+ index = right_children
+ else:
+ break
+ return remove_element
+
+ def size(self):
+ return self.realsize
+
+ def __str__(self):
+ return str(self.maxheap[1 : self.realsize + 1])
+```
+