演算法導論之五堆排序

2021-06-25 08:55:08 字數 3359 閱讀 5304

堆排序的時間複雜度是,與插入排序相似,堆也具有空間原址性,即任何時候都只需要常數個額外的元素空間儲存臨時資料。

1.        堆簡介:

(1)堆是乙個陣列,表示堆的陣列a包括兩個屬性:a.length表示陣列元素的個數,a.heap-size表示有多少個堆元素儲存在該陣列中。

給定一結點的下標i,可以得到其父結點、左孩子和右孩子的下標:

parent(i)

return

left(i)

return 2i

right(i)

return 2i+1

(2)最大堆性質是指除了根以外的所有結點i都要滿足:a[parent(i)] >=a[i],即某個結點的值最多與其父結點一樣大。

堆中的結點高度為該結點到葉結點最長簡單路徑上邊的數目。包含n個元素的堆看做一棵完全二叉樹時,其堆高度為。

2.        維護堆性質

max-heapify是用於維護最大堆性質的過程,輸入為乙個陣列a和乙個下標i。該過程通過對a[i]的值在最大堆中「逐級下降」,從而使得以下標i為根結點的子樹重新遵循最大堆的性質。

max-heapify(a,i)

l = left(i)

r = right(i)

//選出最大結點,將其下標儲存在largest中

if l <= a.heap-sizeand a[l] > a[i]

largest = l

else largest = i

if r <= a.heap-sizeand a[r] > a[largest]

largest = r

//如果a[i]最大,則以i為根結點的子樹已經是最大堆,程式結束

if largest != i

exchangea[i] with a[largest]  //否則交換二值

//交換後,下標為largest的結點的值為原來的a[i],以此節點為根的子樹有可能會//違反最大堆的性質,因此需要對子樹遞迴呼叫

max-heapify(a,largest)         

注意該過程的時間複雜度為,即與樹高呈線性關係。

3.        建堆

採用自底向上的方法利用過程max-heapify可將乙個大小為n=a.length的陣列a[1..n]轉換為最大堆。過程build-max-heap對樹中的其他結點都呼叫一次max-heapify。

build-max-heap(a)

a.heap-size = a.length

for i =  downto 1          //由於a(+1..n)中的元素都是樹的葉節點

max-heapify(a,i)

注意每一次for迴圈的開始,結點i-1,i-2,…,1都是乙個最大堆的根結點。

4.        堆排序演算法

堆排序利用build-max-heap將輸入陣列a[1..n](n=a.length)建成最大堆,因為陣列中的最大元素總在根結點a[1]中,通過把它與a[n]交換,讓該元素放到正確的位置。此時,從堆中去掉結點n,剩餘的結點中,原來根的孩子仍然是最大堆,而新的根結點可能會違背最大堆的性質,因此,呼叫max-heapfy(a,1),從而在a[1..n-1]上構造乙個新的最大堆。以此不斷重複該過程。

heap-sort(a)

build-max-heap(a)

for i =a.length downto 2

exchange a[1] with a[i]

a.heap-size= a.heap-size – 1

max-heapify(a,1)

注意heap-sort的時間複雜度為。

5.        堆的應用:優先佇列

優先佇列是一種用來維護由一組元素構成的集合s的資料結構,其中每乙個元素都有乙個相關的值,稱為關鍵字。最大優先佇列的應用之一是共享計算機系統的作業排程,而最小優先佇列應用之一是基於事件驅動的模擬器。下面介紹最大優先佇列的集中操作。

heap-maximum(a)        //返回最大關鍵字的元素

return a[1]

heap-extract-max(a)  //去掉並返回s中具有最大關鍵字的元素

if a.heap-size < 1

error "heap underflow"

max = a[1]

a[1] = a[a.heap-size]

a.heap-size = a.heap-size -1

max-heapify(a,1)

return max

heap-increase-key(a,i,key)  //將元素i的關鍵字值增加到key

if key

error"new key"

a[i] = key

while i >1 and a[parent(i)] < a[i]

exchangea[i] with a[parent(i)]

i =parent(i)

max-heap-insert(a,key)                 //實現insert操作

a.heap-size =a.heap-size + 1

a[a.heap-size]= -

heap-increase-key(a,a.heap-size,key)

下面的程式是實現最大堆排序:

voidbuild_max_heap(int *a,int len);

voidheap_sort(int *a,int len);

#include

voidexchange(int *a,int i,int j)

intleft_child(int i)

intright_child(int i)

voidmax_heapify(int *a,int len,int index)

if ((r < len) && (a[r] >a[largest]))

if (largest != index)

}

intmain() ;

exchange(source,0,1);

printf("%d%d",source[0],source[1]);

printf("\n");

int i;

heap_sort(source,sizeof(source)/sizeof(source[0]));

for(i=0;i

printf("\n"); }

voidbuild_max_heap(int *a,int len)

for (i=0;i

printf("\n"); }

voidheap_sort(int *a,int len)

}

演算法導論 6 堆排序

堆的分類 最大堆性質 高度 對於堆的一些基本操作 偽 描述 實現 max heapify python實現 123 4567 891011 1213 def max heapify i print max heapify i l left i r right i if l heap size and...

演算法導論之堆排序

堆排序主要是先建堆,轉化為最大堆,每次把最大的乙個 即最大堆的根節點 和最後乙個交換,這樣每次都把當前最大的乙個放到了最後。堆排序演算法中,最關鍵的就是構造初始堆。需要編寫乙個維護大頂堆性質的函式max heapify。當輸入乙個陣列l和乙個下標i,然後呼叫max heapify時,比較l i l ...

演算法導論之堆排序

二叉 堆,是乙個陣列,可以被看成乙個近似的完全二叉樹,樹上的每乙個節點對應於陣列中的乙個元素。除了最底層之外,該樹是完全充滿的,而且是從左向右填充,a.length表示陣列元素的個數,樹的根結點是a 1 這樣給定乙個節點的下標i,我們很容易計算出其父節點 i 2 左子女 2 i 右子女 2 i 1 ...