堆排序演算法(heapsort)
max-heapify過程,其執行時間為о(lg n),是保持最大堆性質的關鍵
build-max-heap過程,以線性時間執行,可以在無序的輸入陣列基礎上構造出最大堆
heapsort過程,執行時間о(n lg n),對乙個陣列原地進行排序
heapsort過程
1、建最大堆
2、將最大元素a[1] 與 a[i] 交換,堆大小heap-size減一
3、重建堆
4、重複2、3操作,直至堆只剩乙個元素
heapsort(a)
build-max-heap(a)
for i <- lenght[a] downto 2
do exchange(a[1], a[i])
heap-size[a] <- heapsize[a] - 1
max-heapify(a, 1)
堆
parent(i)
return ⌊i / 2⌋
left(i)
return 2i
right(i)
return 2i + 1
保持堆性質
max-heapify(a, i)
l <- left(i)
r <- right(i)
if l <= heap-size[a] and a[l] > a[i]
then largest <- l
else largest <- i
if r <= heap-size[a] and a[r] > a[largest]
then largest <- r
if largest ≠ i
then exchange a[i] <-> a[largest]
max-heapify(a, largest)
建堆
對於陣列a[1 .. n]
子陣列a[ (⌊n/2⌋ + 1) .. n ]中的元素都是樹中的葉子,可看作是只含乙個元素的堆。
只需對子陣列a[ 1 .. (⌊n / 2⌋) ]做max-heapify操作
build-max-heap(a)
heap-size[a] <- length[a]
for i <- ⌊ length[a] / 2 ⌋ downto 1
do max-heapify(a, i)
c++實現
#include #include #include int heap_size = 0;
void print(const int *beg, const int *end);
void heapsort(int *ia, size_t size);
void main()
/* 其他函式
*/void swap(int& i, int& j)
void print(const int *beg, const int *end)
/* 堆排序所用到的函式
*/void max_heapify(int *ia, int i)
}void build_max_heap(int *ia, size_t size)
void heapsort(int *ia, size_t size)
}
使用stl heap 有關的函式
make_heap(), pop_heap(), push_heap(), sort_heap(), is_heap;
is_heap() :
原型如下 :
1. bool is_heap(iterator start, iterator end);
->判斷迭代器[start, end] 區間類的元素是否構成乙個堆. 是返回true ,否則返回 false.
2. bool is_heap(iterator start, iterator end, strictweakordering cmp);
->判斷迭代器[start, end] 區間類的元素在cmp條件下是否構成乙個堆. 是返回true ,否則返回 false.
make_heap() :
原型如下 :
1.void make_heap( random_access_iterator start, random_access_iterator end );
2.void make_heap( random_access_iterator start, random_access_iterator end, strictweakordering cmp);
->以 迭代器[start , end] 區間內的元素生成乙個堆. 預設使用 元素型別 的 < 操作符 進行判斷堆的型別, 因此生成的是大頂堆 .
->當使用了 版本2時, 系統使用 使用者定義的 cmp 函式來構建乙個堆
->值得注意的是, make_heap 改變了 迭代器所指向的 容器 的值.
pop_heap() :
原型如下 :
1.void pop_heap( random_access_iterator start, random_access_iterator end );
2. void pop_heap( random_access_iterator start, random_access_iterator end, strictweakordering cmp);
->pop_heap() 並不是真的把最大(最小)的元素從堆中彈出來. 而是重新排序堆. 它把首元素和末元素交換,然後將[first,last-1)的資料再做成乙個堆。
此時, 原來的 首元素 位於迭代器 end-1 的位置, 它已不再屬於堆的一員!
->如果使用了 版本2 , 在交換了 首元素和末元素後 ,使用 cmp 規則 重新構建乙個堆.
push_heap() :
原型如下 :
1.void push_heap( random_access_iterator start, random_access_iterator end );
2. void push_heap( random_access_iterator start, random_access_iterator end, strictweakordering cmp);
-> 演算法假設迭代器區間[start, end-1)內的元素已經是乙個有效堆, 然後把 end-1 迭代器所指元素加入堆.
-> 如果使用了 cmp 引數, 將使用 cmp 規則構建堆.
sort_heap() :
原型如下 :
1.void sort_heap (random_access_iterator start, random_access_iterator end);
2.void sort_heap (random_access_iterator start, random_access_iterator end, strictweakordering cmp);
-> 堆結構被完全破壞, 相當於對元素進行排序, 效果和排序演算法類似.
-> 如果使用了 cmp 引數, 將使用 cmp 規則排序堆.
#include #include #include #include #include using namespace std;
void print(vector::const_iterator beg, vector::const_iterator end);
void main()
演算法導論 堆排序習題
1.怎樣利用最大 小 堆構成的優先實現先進先出佇列或者棧 開始看這道題沒有弄清以什麼優先,原來是先進先出佇列只要保證先進來優先順序高,棧保證後進來優先順序高,然後每次彈出堆頂元素即可 2.如何在logn時間裡刪除乙個元素 思路和如何在堆中增加乙個元素是一樣的,因為堆要的形狀要保證是一顆完全二叉樹,決...
演算法導論 堆排序實現
我建立了乙個heap的資料結構,而不是像stl那樣使用函式解決堆排序,當然stl的比較優雅一點,我只是提供第二個思路 ifndef heap sort h define heap sort h include include include ifdef debug include endif deb...
學習演算法導論 堆排序
演算法導論 第三版書中陣列下標是從1開始的,但是這裡從0開始。堆分為兩種,即最大堆和最小堆,最大堆的定義為 當陣列a大小為n時 a中有n個元素 若2 i 1 a 2 i 1 若2 i 2 a 2 i 2 則這樣的資料結構稱為最大堆。說白了就是根節點 包括子樹的根節點 的值不小於左節點和右節點的值 如...