-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e17145d
commit 56ab723
Showing
1 changed file
with
174 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
### Heap (Priority Queue) | ||
|
||
A **heap** is a specialized tree-based data structure used primarily for efficient access to the maximum or minimum element. It is often implemented as a binary tree and can be used to maintain a priority queue, which allows for quick retrieval of the highest or lowest priority element. | ||
|
||
--- | ||
|
||
#### Key Concepts | ||
|
||
1. **Purpose** | ||
|
||
- Heaps are used to get the minimum or maximum element from a collection in constant time, O(1). | ||
- Insertion and deletion of elements are performed in logarithmic time, O(log n). | ||
|
||
2. **Types of Heaps** | ||
- **Min-Heap**: The root node is the smallest element, and every parent node is less than or equal to its children. | ||
- **Max-Heap**: The root node is the largest element, and every parent node is greater than or equal to its children. | ||
|
||
--- | ||
|
||
### Heap Properties | ||
|
||
1. **Structure Property** | ||
|
||
- The heap is a **complete binary tree**, meaning all levels are completely filled except possibly the last level, which must be filled from left to right. | ||
- This ensures efficient use of space and enables fast access to elements. | ||
|
||
2. **Order Property** | ||
- In a **min-heap**, the value of the root node is smaller than both its children. | ||
- In a **max-heap**, the value of the root node is larger than both its children. | ||
|
||
#### Example of a Max-Heap: | ||
|
||
``` | ||
14 | ||
/ \ | ||
19 16 | ||
/ \ | ||
21 26 | ||
``` | ||
|
||
### Differences from Binary Search Tree (BST) | ||
|
||
- **Duplicates**: Heaps can contain duplicate values, whereas BSTs do not allow duplicate nodes. | ||
- **Ordering**: In a heap, only the parent-child relationship matters for ordering. In a BST, all nodes in the left subtree are smaller than the root, and all nodes in the right subtree are larger. | ||
|
||
--- | ||
|
||
### Array Representation of Heaps | ||
|
||
A heap is generally implemented using an array. Given the complete binary tree property, the elements can be stored in an array such that: | ||
|
||
- The **root** is at index 1 (index 0 is typically unused). | ||
- For any node at index i: | ||
- The **left child** is at index 2i. | ||
- The **right child** is at index 2i + 1. | ||
- The **parent** is at index i // 2. | ||
|
||
#### Example Array Representation: | ||
|
||
For the tree: | ||
|
||
``` | ||
14 | ||
/ \ | ||
19 16 | ||
/ \ | ||
21 26 | ||
``` | ||
|
||
The array representation would be: | ||
|
||
``` | ||
0 1 2 3 4 5 | ||
----------------------------- | ||
| | 14 | 19 | 16 | 21 | 26 | | ||
----------------------------- | ||
``` | ||
|
||
--- | ||
|
||
### Heap Operations | ||
|
||
1. **Insert Operation (`push`)** | ||
|
||
- Insert a new element at the end of the array. | ||
- **Percolate up** (or bubble up) the element to restore the heap property by comparing the element with its parent and swapping if necessary. | ||
- Time complexity: O(\log n), where n is the number of elements. | ||
|
||
2. **Delete Operation (`pop`)** | ||
- Remove the root element (either the minimum or maximum). | ||
- Replace the root with the last element in the heap. | ||
- **Percolate down** (or bubble down) the root element to restore the heap property by comparing with its children and swapping if necessary. | ||
- Time complexity: O(log n). | ||
|
||
--- | ||
|
||
### Python Implementation of Heap | ||
|
||
```python | ||
class Heap: | ||
def __init__(self): | ||
self.heap = [0] # Initialize heap with a dummy element at index 0 | ||
|
||
def push(self, val): | ||
# Insert new value at the end | ||
self.heap.append(val) | ||
i = len(self.heap) - 1 | ||
|
||
# Percolate up | ||
while i > 1 and self.heap[i] < self.heap[i // 2]: | ||
self.heap[i], self.heap[i // 2] = self.heap[i // 2], self.heap[i] | ||
i //= 2 # Move to the parent node | ||
|
||
def pop(self): | ||
if len(self.heap) == 1: | ||
return None # Heap is empty | ||
|
||
if len(self.heap) == 2: | ||
return self.heap.pop() # Only one element | ||
|
||
res = self.heap[1] # The root value (min or max) | ||
self.heap[1] = self.heap.pop() # Replace root with the last element | ||
i = 1 | ||
|
||
# Percolate down | ||
while 2 * i < len(self.heap): | ||
# Check if right child exists and is smaller than the left child | ||
if 2 * i + 1 < len(self.heap) and self.heap[2 * i + 1] < self.heap[2 * i]: | ||
# Swap with right child if needed | ||
if self.heap[i] > self.heap[2 * i + 1]: | ||
self.heap[i], self.heap[2 * i + 1] = self.heap[2 * i + 1], self.heap[i] | ||
i = 2 * i + 1 | ||
else: | ||
break | ||
# Otherwise, swap with the left child | ||
elif self.heap[i] > self.heap[2 * i]: | ||
self.heap[i], self.heap[2 * i] = self.heap[2 * i], self.heap[i] | ||
i = 2 * i | ||
else: | ||
break | ||
|
||
return res | ||
|
||
def heapify(self, arr): | ||
# Convert any array into a heap | ||
arr = [0] + arr # Add dummy element at index 0 | ||
self.heap = arr | ||
cur = (len(self.heap) - 1) // 2 # Start with the first non-leaf node | ||
|
||
while cur > 0: | ||
# Percolate down | ||
i = cur | ||
while 2 * i < len(self.heap): | ||
if 2 * i + 1 < len(self.heap) and self.heap[2 * i + 1] < self.heap[2 * i]: | ||
if self.heap[i] > self.heap[2 * i + 1]: | ||
self.heap[i], self.heap[2 * i + 1] = self.heap[2 * i + 1], self.heap[i] | ||
i = 2 * i + 1 | ||
else: | ||
break | ||
elif self.heap[i] > self.heap[2 * i]: | ||
self.heap[i], self.heap[2 * i] = self.heap[2 * i], self.heap[i] | ||
i = 2 * i | ||
else: | ||
break | ||
cur -= 1 | ||
``` | ||
|
||
--- | ||
|
||
### Time Complexities | ||
|
||
- **Insertion (`push`)**: O(log n) | ||
- **Deletion (`pop`)**: O(log n) | ||
- **Heapify**: O(n) – It can convert any array into a heap efficiently. |