STL中的heap演算法
阿新 • • 發佈:2019-01-03
就排序而言,heap是一種特別的元素組織方式,應用於heap排序法。Heap可以被視為一個以序列式集合實現而成的二叉樹。具有兩大性質:
- 第一個元素總是最大
- 總是能夠在對數時間內增加或者移除一個元素。
======
Heap是實現優先順序佇列的一個理想結構,因此heap演算法也被priority_queue容器使用。為了處理heap,STL提供了四個演算法:
- make_heap():將某區間內的元素轉化為heap
- push_heap():對heap增加一個元素
- pop_heap():對heap取出下一個元素
- sort_heap():將heap轉化為一個已排序序列。
同樣的,可以給上述函式傳入一個二元的謂詞作為排序準則。預設的排序準則是operator<。
void make_heap(RandomAccessIterator beg,RandomAccessIterator end/*,BinaryPredicate op*/)
- 兩種形式都將[beg,end)區間內的元素轉化為heap
- 複雜度:線性,至多執行3*n次比較
void push_heap(RandomAccessIterator beg,RandomAccessIterator end/*,BinaryPredicate op*/)
- 將end之前的最後一個元素加入原本就是heap的[beg,end-1)區間內,使整個[beg,end)區間成為一個heap
- 呼叫者必須保證
- 複雜度:對數
void pop_heap(RandomAccessIterator beg,RandomAccessIterator end/*,BinaryPredicate op*/)
- 將heap[beg,end)內的最高元素(即第一個元素)移到最後位置,並將[beg,end-1)內的元素組織起來,從新組成heap
- 呼叫者必須保證,進入函式時,[beg,end)區間內的元素(在相同的排序準則下)原本便已形成一個heap
- 複雜度:對數
void sort_heap(RandomAccessIterator beg,RandomAccessIterator end/*,BinaryPredicate op*/ )
- 將heap[beg,end)轉換為一個已排序序列
- 此演算法一旦結束,該區間就不再是一個heap
- 呼叫者必須保證,進入函式時,[beg,end)區間內的元素(在相同的排序準則下)原本便已形成一個heap
int main()
{
vector<int> coll;
insertElements(coll, 3, 7);
insertElements(coll, 5, 9);
insertElements(coll, 1, 4);
printElements(coll,"on entry: ");
make_heap(coll.begin(), coll.end());
printElements(coll,"after make_heap(): ");
pop_heap(coll.begin(), coll.end());
coll.pop_back();
printElements(coll, "after pop_heap(): ");
coll.push_back(17);
push_heap(coll.begin(), coll.end());
printElements(coll, "after push_heap(): ");
sort_heap(coll.begin(), coll.end());
printElements(coll, "after sort_heap(): ");
return 0;
}
呼叫make_heap()之後,元素被排序為heap:
9 8 6 7 7 5 5 3 6 4 1 2 3 4
如果把這些元素轉換為二叉樹
可以看到每個元素都小於或者等於其父親結點。