演算法導論 堆排序

2021-06-12 11:36:01 字數 3825 閱讀 2165

堆排序演算法(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 則這樣的資料結構稱為最大堆。說白了就是根節點 包括子樹的根節點 的值不小於左節點和右節點的值 如...