ADT - heap(堆)
阿新 • • 發佈:2018-04-29
str com define 合並 iostream color 進行 建堆 nbsp
二叉堆:
以前寫過二叉堆,但很少使用,快忘了。最近又查了一些關於堆的資料,於是重新熟悉一下這種數據結構。
一個快速又簡單的方式建立二叉堆,僅使用簡單vector(或者數組也行):
#include "stdafx.h" #include <iostream> #include <vector> #define LeftChild(i) (2*(i) + 1) #define RightChild(i) (2*((i) + 1)) template<class T> void swap(T & a, T & b) { T tem = a; a = b; b = tem; } class Heap { public: /* 上濾插入 */ void up_insert(int val, std::vector<int> & values, int top); /* 調用上濾插入建立堆 */ void up2build(std::vector<int> & values); /* 下濾插入 */ void down_insert(std::vector<int> & values, int i, int size); /* 調用下濾插入建立堆 */ void down2build(std::vector<int> & values); /* 堆排序 */ void sort(std::vector<int> & values); }; void Heap::up_insert(int val, std::vector<int> & values, int top) { size_t i; for (i = top; i > 0 && values[i >> 1] < val; i >>= 1) values[i] = values[i >> 1]; values[i] = val; } void Heap::up2build(std::vector<int> & values) { int top = 0; for (auto v : values) { up_insert(v, values, top); ++top; } } void Heap::down_insert(std::vector<int> & values, int i, int size) { int last = values[i]; for (int Child; LeftChild(i) < size; i = Child) { Child = LeftChild(i); if (Child != size - 1 && values[Child + 1] > values[Child]) Child++; if (last < values[Child]) values[i] = values[Child]; else break; } values[i] = last; } void Heap::down2build(std::vector<int> & values) { int size = values.size() - 1; for (int i = size >> 1; i >= 0; i--) { down_insert(values, i, size); } } void Heap::sort(std::vector<int> & values) { int size = values.size() - 1; down2build(values); for (int i = size; i > 0; i--) { swap(values[0], values[i]); down_insert(values, 0, i); } } int main() { Heap heap; std::vector<int> values { 5345,332,2341,498,248,89,239,4825,8,43,9892,872,1843 }; //heap.build(values); heap.sort(values); for (auto v : values) std::cout << v << std::endl; getchar(); return 0; }
up_build是形如‘上濾’的過程,平均情況時間復雜度為θ(n),因為up_insert函數只花費θ(1)的平均時間。最壞情況為O(n),空間復雜度O(1);
down_build是形如‘下濾’的過程,時間復雜度為O(n),空間復雜度O(1),有點不可思議,不過這裏《數據結構與算法分析》書中說下濾建堆也是O(n),但知乎上有證明下濾是O(nlgn) = = 難道是我看錯了?其實我也覺得自頂向下建堆的復雜度為O(nlgn))。
左式堆:
左式堆的性質:任意節點的左孩子的NPL(null path length - 零路徑長)至少等於右孩子的NPL,這樣的條件使得左式堆十分不平衡。左式堆的基本操作是進行堆合並。
NPL的定義:任一節點到葉節點的最短路徑的長。
參考資料:
1.《數據結構與算法分析》第6章 - 堆。
2.知乎相關問題
ADT - heap(堆)