二叉堆是具有以下属性的二叉树。
1)它是一棵完整的树(所有级别都被完全填充,除了最后一个级别,最后一个级别尽可能保留所有键)。二叉堆的这个特性使得它们适合存储在数组中。
2) 二叉堆是最小堆或最大堆。在最小二叉堆中,根处的键必须是二叉堆中所有键中的最小值。对于二叉树中的所有节点,相同的属性必须递归为真。 Max Binary Heap 类似于 MinHeap。
最小堆示例:
10 10
/ \ / \
20 100 15 30
/ / \ / \
30 40 50 100 40
二叉堆是如何表示的?
二叉堆是一棵完全二叉树。二叉堆通常表示为一个数组。
- 根元素将位于 Arr[0]。
- 下表显示了第 i个节点的其他节点的索引,即 Arr[i]:
Arr[(i-1)/2] Returns the parent node Arr[(2*i)+1] Returns the left child node Arr[(2*i)+2] Returns the right child node 实现数组表示的遍历方法是Level Order
有关详细信息,请参阅二进制堆的数组表示。
堆的应用:
1)堆排序:堆排序使用二叉堆在 O(nLogn) 时间内对数组进行排序。2)优先队列:优先队列可以使用二叉堆高效实现,因为它支持 O(logn) 时间内的 insert()、delete() 和 extractmax()、reduceKey() 操作。二项堆和斐波那契堆是二叉堆的变体。这些变化也有效地执行联合。
3)图算法:优先队列特别用于图算法,如 Dijkstra 的最短路径和 Prim 的最小生成树。
4)使用堆可以有效地解决许多问题。例如,请参见以下内容。
a) 数组中的第 K 个最大元素。
b) 对一个几乎已排序的数组进行排序/
c) 合并 K 个排序数组。最小堆上的操作:
1) getMini():返回Min Heap的根元素。此操作的时间复杂度为 O(1)。2) extractMin():从MinHeap中移除最小元素。此操作的时间复杂度为 O(Logn),因为此操作需要在移除 root 后维护堆属性(通过调用 heapify())。
3) decreaseKey():减少key的值。这个操作的时间复杂度是 O(Logn)。如果一个节点的下降键值大于该节点的父节点,那么我们不需要做任何事情。否则,我们需要向上遍历以修复违反的堆属性。
4) insert():插入一个新的key需要O(Logn)时间。我们在树的末尾添加一个新键。如果新键大于它的父键,那么我们不需要做任何事情。否则,我们需要向上遍历以修复违反的堆属性。
5) delete():删除一个key也需要O(Logn)时间。我们通过调用reduceKey() 用最小无穷大替换要删除的键。在decreaseKey()之后,负无穷值必须达到root,所以我们调用extractMin()来移除key。
下面是基本堆操作的实现。
C++
// A C++ program to demonstrate common Binary Heap Operations #include
#include using namespace std; // Prototype of a utility function to swap two integers void swap(int *x, int *y); // A class for Min Heap class MinHeap { int *harr; // pointer to array of elements in heap int capacity; // maximum possible size of min heap int heap_size; // Current number of elements in min heap public: // Constructor MinHeap(int capacity); // to heapify a subtree with the root at given index void MinHeapify(int ); int parent(int i) { return (i-1)/2; } // to get index of left child of node at index i int left(int i) { return (2*i + 1); } // to get index of right child of node at index i int right(int i) { return (2*i + 2); } // to extract the root which is the minimum element int extractMin(); // Decreases key value of key at index i to new_val void decreaseKey(int i, int new_val); // Returns the minimum key (key at root) from min heap int getMin() { return harr[0]; } // Deletes a key stored at index i void deleteKey(int i); // Inserts a new key 'k' void insertKey(int k); }; // Constructor: Builds a heap from a given array a[] of given size MinHeap::MinHeap(int cap) { heap_size = 0; capacity = cap; harr = new int[cap]; } // Inserts a new key 'k' void MinHeap::insertKey(int k) { if (heap_size == capacity) { cout << "\nOverflow: Could not insertKey\n"; return; } // First insert the new key at the end heap_size++; int i = heap_size - 1; harr[i] = k; // Fix the min heap property if it is violated while (i != 0 && harr[parent(i)] > harr[i]) { swap(&harr[i], &harr[parent(i)]); i = parent(i); } } // Decreases value of key at index 'i' to new_val. It is assumed that // new_val is smaller than harr[i]. void MinHeap::decreaseKey(int i, int new_val) { harr[i] = new_val; while (i != 0 && harr[parent(i)] > harr[i]) { swap(&harr[i], &harr[parent(i)]); i = parent(i); } } // Method to remove minimum element (or root) from min heap int MinHeap::extractMin() { if (heap_size <= 0) return INT_MAX; if (heap_size == 1) { heap_size--; return harr[0]; } // Store the minimum value, and remove it from heap int root = harr[0]; harr[0] = harr[heap_size-1]; heap_size--; MinHeapify(0); return root; } // This function deletes key at index i. It first reduced value to minus // infinite, then calls extractMin() void MinHeap::deleteKey(int i) { decreaseKey(i, INT_MIN); extractMin(); } // A recursive method to heapify a subtree with the root at given index // This method assumes that the subtrees are already heapified void MinHeap::MinHeapify(int i) { int l = left(i); int r = right(i); int smallest = i; if (l < heap_size && harr[l] < harr[i]) smallest = l; if (r < heap_size && harr[r] < harr[smallest]) smallest = r; if (smallest != i) { swap(&harr[i], &harr[smallest]); MinHeapify(smallest); } } // A utility function to swap two elements void swap(int *x, int *y) { int temp = *x; *x = *y; *y = temp; } // Driver program to test above functions int main() { MinHeap h(11); h.insertKey(3); h.insertKey(2); h.deleteKey(1); h.insertKey(15); h.insertKey(5); h.insertKey(4); h.insertKey(45); cout << h.extractMin() << " "; cout << h.getMin() << " "; h.decreaseKey(2, 1); cout << h.getMin(); return 0; }
Python
# A Python program to demonstrate common binary heap operations # Import the heap functions from python library from heapq import heappush, heappop, heapify # heappop - pop and return the smallest element from heap # heappush - push the value item onto the heap, maintaining # heap invarient # heapify - transform list into heap, in place, in linear time # A class for Min Heap class MinHeap: # Constructor to initialize a heap def __init__(self): self.heap = [] def parent(self, i): return (i-1)/2 # Inserts a new key 'k' def insertKey(self, k): heappush(self.heap, k) # Decrease value of key at index 'i' to new_val # It is assumed that new_val is smaller than heap[i] def decreaseKey(self, i, new_val): self.heap[i] = new_val while(i != 0 and self.heap[self.parent(i)] > self.heap[i]): # Swap heap[i] with heap[parent(i)] self.heap[i] , self.heap[self.parent(i)] = ( self.heap[self.parent(i)], self.heap[i]) # Method to remove minium element from min heap def extractMin(self): return heappop(self.heap) # This functon deletes key at index i. It first reduces # value to minus infinite and then calls extractMin() def deleteKey(self, i): self.decreaseKey(i, float("-inf")) self.extractMin() # Get the minimum element from the heap def getMin(self): return self.heap[0] # Driver pgoratm to test above function heapObj = MinHeap() heapObj.insertKey(3) heapObj.insertKey(2) heapObj.deleteKey(1) heapObj.insertKey(15) heapObj.insertKey(5) heapObj.insertKey(4) heapObj.insertKey(45) print heapObj.extractMin(), print heapObj.getMin(), heapObj.decreaseKey(2, 1) print heapObj.getMin() # This code is contributed by Nikhil Kumar Singh(nickzuck_007)
C#
// C# program to demonstrate common // Binary Heap Operations - Min Heap using System; // A class for Min Heap class MinHeap{ // To store array of elements in heap public int[] heapArray{ get; set; } // max size of the heap public int capacity{ get; set; } // Current number of elements in the heap public int current_heap_size{ get; set; } // Constructor public MinHeap(int n) { capacity = n; heapArray = new int[capacity]; current_heap_size = 0; } // Swapping using reference public static void Swap
(ref T lhs, ref T rhs) { T temp = lhs; lhs = rhs; rhs = temp; } // Get the Parent index for the given index public int Parent(int key) { return (key - 1) / 2; } // Get the Left Child index for the given index public int Left(int key) { return 2 * key + 1; } // Get the Right Child index for the given index public int Right(int key) { return 2 * key + 2; } // Inserts a new key public bool insertKey(int key) { if (current_heap_size == capacity) { // heap is full return false; } // First insert the new key at the end int i = current_heap_size; heapArray[i] = key; current_heap_size++; // Fix the min heap property if it is violated while (i != 0 && heapArray[i] < heapArray[Parent(i)]) { Swap(ref heapArray[i], ref heapArray[Parent(i)]); i = Parent(i); } return true; } // Decreases value of given key to new_val. // It is assumed that new_val is smaller // than heapArray[key]. public void decreaseKey(int key, int new_val) { heapArray[key] = new_val; while (key != 0 && heapArray[key] < heapArray[Parent(key)]) { Swap(ref heapArray[key], ref heapArray[Parent(key)]); key = Parent(key); } } // Returns the minimum key (key at // root) from min heap public int getMin() { return heapArray[0]; } // Method to remove minimum element // (or root) from min heap public int extractMin() { if (current_heap_size <= 0) { return int.MaxValue; } if (current_heap_size == 1) { current_heap_size--; return heapArray[0]; } // Store the minimum value, // and remove it from heap int root = heapArray[0]; heapArray[0] = heapArray[current_heap_size - 1]; current_heap_size--; MinHeapify(0); return root; } // This function deletes key at the // given index. It first reduced value // to minus infinite, then calls extractMin() public void deleteKey(int key) { decreaseKey(key, int.MinValue); extractMin(); } // A recursive method to heapify a subtree // with the root at given index // This method assumes that the subtrees // are already heapified public void MinHeapify(int key) { int l = Left(key); int r = Right(key); int smallest = key; if (l < current_heap_size && heapArray[l] < heapArray[smallest]) { smallest = l; } if (r < current_heap_size && heapArray[r] < heapArray[smallest]) { smallest = r; } if (smallest != key) { Swap(ref heapArray[key], ref heapArray[smallest]); MinHeapify(smallest); } } // Increases value of given key to new_val. // It is assumed that new_val is greater // than heapArray[key]. // Heapify from the given key public void increaseKey(int key, int new_val) { heapArray[key] = new_val; MinHeapify(key); } // Changes value on a key public void changeValueOnAKey(int key, int new_val) { if (heapArray[key] == new_val) { return; } if (heapArray[key] < new_val) { increaseKey(key, new_val); } else { decreaseKey(key, new_val); } } } static class MinHeapTest{ // Driver code public static void Main(string[] args) { MinHeap h = new MinHeap(11); h.insertKey(3); h.insertKey(2); h.deleteKey(1); h.insertKey(15); h.insertKey(5); h.insertKey(4); h.insertKey(45); Console.Write(h.extractMin() + " "); Console.Write(h.getMin() + " "); h.decreaseKey(2, 1); Console.Write(h.getMin()); } } // This code is contributed by // Dinesh Clinton Albert(dineshclinton)
输出:
2 4 1
堆上的编码实践
关于堆的所有文章
堆测验
PriorityQueue: Java库中的二叉堆实现如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。