算法导论学习笔记 第6章 堆排序
?在本章中介紹了另一種排序算法:堆排序(heapsort)。與歸排序一樣,但不同于插入排序的是,堆排序的時間復(fù)雜度式(Onlgn)。而與插入排序相同,但不同于歸并排序的是,堆排序同樣具有空間原址性(我理解的意思是可以實(shí)現(xiàn)就地排序):任何時候都只需要常數(shù)個額外的元素空間存儲臨時數(shù)據(jù)。因此,堆排序是集合了歸并排序和插入排序兩種排序算法有點(diǎn)的一種排序算法。?
?堆的定義如下:堆是一個數(shù)組,它可以被看成一個近似的完全二叉樹(圖6-1)。完全二叉樹中所有非終端結(jié)點(diǎn)的值均不大于(或不小于)其左右孩子結(jié)點(diǎn)的值。因此,若{k1, k2, ..., kn }是堆,則堆頂元素必為序列中n個元素的最小值(或最小值)。
? 如果把堆看成是一顆樹,定義一個堆中的結(jié)點(diǎn)的高度為該結(jié)點(diǎn)到頁結(jié)點(diǎn)最長簡單路徑邊上的數(shù)目,既然一個包含n個元素的堆可以看做一顆完全二叉樹,那么該堆的高度是O(lgn)。因此,堆結(jié)構(gòu)上的一些基本操作的運(yùn)行時間與樹的高度成正比,即時間復(fù)雜度為O(lgn)。下面將介紹對的一些基本過程:
- MAX-HEAPIFY過程:其時間復(fù)雜度為O(lgn),它是維護(hù)最大堆性質(zhì)的關(guān)鍵。
- BUILD-MAX-HEAP過程: 具有線性時間復(fù)雜度,功能是從無序的輸入數(shù)據(jù)數(shù)組中構(gòu)造一個最大堆。
- HEAP-SORT過程:時間復(fù)雜度為O(nlgn),功能是對一個數(shù)組進(jìn)行原址排序。
- MAX-HEAP-INSERT、HEAP-EXTRACT-MAX、HEAP-INCREASE-KEY和HEAP-MAXIMUM過程:時間復(fù)雜度為O(lgn),功能是利用堆實(shí)現(xiàn)一個優(yōu)先隊列。
6.2 維護(hù)堆的性質(zhì)
? MAX-HEAPIFY是用于維護(hù)最大堆性質(zhì)的重要過程。它的輸入一個數(shù)組A和一個下標(biāo)i。調(diào)用MAX-HEAPIFY時,假定根結(jié)點(diǎn)LEFT(i)和RIGHT(i)的二叉樹都是最大堆,但是A[i]有可能小于其孩子,這樣就違背了最大堆的性質(zhì)。MAX-HEAPIFY通過讓A[i]的值在最大堆中“逐級下降”,從而使得下標(biāo)i為根節(jié)點(diǎn)的子樹重新遵循最大堆的性質(zhì)。采用C語言編寫的代碼如下:
void maxHeapIFY(int *arr, int length, int i){int l = LEFT(i);int r = RIGHT(i);int largest=0;if (l<=length && arr[l]>a[i] )largest = l;elselargest = i;if(r<=length && arr[r]>arr[largest])largest = r;if(largest != i){int temp = arr[i];arr[i] = largest;largest = temp;maxHeapIFY(arr, length, largest);}}
圖6-2表示了MAX-HEAPIFY的執(zhí)行過程。在程序的每一步中,從A[i]、A[LEFT(i)]和A[RIGHT(i)]中選出最大值,并將其下標(biāo)存儲在largest中。從圖中可以看出,在節(jié)點(diǎn)i=2時,不滿足最大堆的要求,需要進(jìn)行調(diào)整,選擇節(jié)點(diǎn)2的左右孩子中最大一個進(jìn)行交換,然后檢查交換后的節(jié)點(diǎn)i=4是否滿足最大堆的要求,從圖看出不滿足,接著進(jìn)行調(diào)整,直到?jīng)]有交換為止。MAX-HEAPIFY的時間復(fù)雜度為O(h)。
6.3 建堆
? 從一個無需序列建堆的過程就是一個反復(fù)“篩選”的過程。若將此序列看成是一個完全二叉樹,則最后一個非終端結(jié)點(diǎn)是第(n/2)向下取整,由此,從第n/2個元素開始,逐個調(diào)用MAX-HEAPIFY(A, i)過程。調(diào)整過程如下圖所示:
采用c語言實(shí)現(xiàn)的建堆的代碼如下:
void bulidMaxHeap(int *arr, int length){for int i = length/2; i>0; --i){maxHeapIFY(arr, length, i);} }
6.4 堆排序算法
? 初始時候,堆排序算法利用BUILD-MAX-HEAP將輸入數(shù)組A[1.. n]建成最大堆,其中A=A.length。因?yàn)閿?shù)組中的最大元素總在根結(jié)點(diǎn)A[1]中,首先交換A[1]與A[n],可以讓該元素放到正確的位置。此時從堆中去掉結(jié)點(diǎn)n,剩余的結(jié)點(diǎn)中,原來的根的孩子結(jié)點(diǎn)仍然是最大堆,而新的根結(jié)點(diǎn)可能會違背最大堆的性質(zhì)。為了維護(hù)最大堆的性質(zhì),我們要做的是調(diào)用MAX-HEAPIFY(A, 1),從而在A[1.. n-1]上重新構(gòu)造一個最大堆。堆排序算法就是不斷的重復(fù)這一過程,直到堆的大小從n-1降到2。下圖給出了在HEAPSORT的第一行建立初始最大堆之后,堆排序操作的一個例子。
采用C語言實(shí)現(xiàn)的代碼如下:
void heapSort(int *arr,int length) {int i,temp;//bulid max heapbuildMaxHeap(arr,length);i=length;//exchange the first value to the last unitl i=1while(i>1){temp = arr[i];arr[i] = arr[1];arr[1] =temp;i--;//adjust max heap,make sure the fisrt value is the largestbuildMaxHeap(arr,i,1);} } ? 堆排序算法時間復(fù)雜度:調(diào)整堆過程滿足遞歸式T(n)<=T(2n/3)+θ(1),有master定義可以知道T(n) = O(lgn),堆排序過程中執(zhí)行一個循環(huán),調(diào)用最大堆調(diào)整函數(shù),總的時間復(fù)雜度為O(nlgn)。寫本博客的時候參考了Anker的博客,博客中所用到的圖片也是取自這里。
總結(jié)
以上是生活随笔為你收集整理的算法导论学习笔记 第6章 堆排序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 算法导论读书笔记 第4章 分治策略
- 下一篇: 算法导论学习笔记 6.5 优先队列