1、堆排序演算法描述:
(1)定義
n個關鍵字序列kl,k2,…,kn稱為(heap),當且僅當該序列滿足如下性質(簡稱為堆性質):
1)ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n/2),當然,這是小根堆,大根堆則換成》=號。//k(i)相當於
二叉樹的非
葉子結點,k(2i)則是左子節點,k(2i+1)是右子節點
2)若將此序列所儲存的向量r[1..n]看做是一棵完全二叉樹的
儲存結構
,則堆實質上是滿足如下性質的完全二叉樹:
樹中任一非葉子結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。
(2)用大根堆排序的基本思想
① 先將初始檔案r[1..n]建成乙個大根堆,此堆為初始的無序區
② 再將關鍵字最大的記錄r[1](即堆頂)和無序區的最後乙個記錄r[n]交換,由此得到新的無序區r[1..n-1]和有序區r[n],且滿足r[1..n-1].keys≤r[n].key
③由於交換後新的根r[1]可能違反堆性質,故應將當前無序區r[1..n-1]調整為堆。然後再次將r[1..n-1]中關鍵字最大的記錄r[1]和該區間的最後乙個記錄r[n-1]交換,由此得到新的無序區r[1..n-2]和有序區r[n-1..n],且仍滿足關係r[1..n-2].keys≤r[n-1..n].keys,同樣要將r[1..n-2]調整為堆。
……直到無序區只有乙個元素為止。
(3)大根堆排序演算法的基本操作:
①建堆,建堆是不斷調整堆的過程,從len/2處開始調整,一直到第乙個節點,此處len是堆中元素的個數。建堆的過程是線性的過程,從len/2到0處一直呼叫調整堆的過程,相當於o(h1)+o(h2)…+o(hlen/2) 其中h表示節點的深度,len/2表示節點的個數,這是乙個求和的過程,結果是線性的o(n)。
②調整堆:調整堆在構建堆的過程中會用到,而且在堆排序過程中也會用到。利用的思想是比較節點i和它的孩子節點left(i),right(i),選出三者最大(或者最小)者,如果最大(小)值不是節點i而是它的乙個孩子節點,那邊互動節點i和該節點,然後再呼叫調整堆過程,這是乙個遞迴的過程。調整堆的過程時間複雜度與堆的深度有關係,是lgn的操作,因為是沿著深度方向進行調整的。
③堆排序:堆排序是利用上面的兩個過程來進行的。首先是根據元素構建堆。然後將堆的根節點取出(一般是與最後乙個節點進行交換),將前面len-1個節點繼續進行堆調整的過程,然後再將根節點取出,這樣一直到所有節點都取出。堆排序過程的時間複雜度是o(nlgn)。因為建堆的時間複雜度是o(n)(呼叫一次);調整堆的時間複雜度是lgn,呼叫了n-1次,所以堆排序的時間複雜度是o(nlgn)。
2、堆的儲存
一般用陣列來表示堆,若根結點存在序號0處, i結點的父結點下標就為(i-1)/2。i結點的左右子結點下標分別為
2*i+1
和2*i+2
。3、堆排序演算法實現(最大堆)
#include void printarray(int thearray, int n)
std::cout << std::endl;
}void adjustheap(int thearray, int n, int start) //從start索引處結點開始調整
} if(leftindex < n) //start索引處結點存在左孩子結點,但不一定存在右孩子結點
} adjustheap(thearray, n, start-1); //再次遞迴調整start索引處的上乙個結點
}void constructheap(int thearray, int n)
void heapsort(int thearray, int n)
int main(int argc, char *argv) ;
int length = sizeof(myarray) / sizeof(myarray[0]);
constructheap(myarray, length);
heapsort(myarray, length);
printarray(myarray, length);
return 0;
}
4、堆的時間複雜度和空間複雜度
堆的最好、最壞以及平均時間複雜度是o(nlogn).
堆的空間複雜度是o(1).
感想:剛開始實現建立堆時,以為需要建立乙個二叉樹輔助幫助,其實這個所謂堆(即完全二叉樹)只是邏輯結構,真實的物理結構還是那個順序陣列,在建立大堆或小堆的過程中,均是以順序陣列為基礎,而邏輯上是操作一顆完全二叉樹,故完全不需要建立乙個輔助完全二叉樹。
堆排序實現
今天抽空寫了個堆排序的演算法,廢話不多說,直接上源 include include includeusing namespace std define maxsize 6 void print int a,int size maxsize void percolate up int a,int si...
實現堆排序
堆排序是在程式設計中經常用到的東西,在c 的stl底層裡面有make heap,push heap,pop heap 和 sort heap四個介面函式,我們用到的最多的是stl中的priority queue,其中的底層也是利用前面幾個函式實現的。下面我們就自己實現以下堆排序,主要包括調整堆結構,...
堆排序實現
堆排序的實現與優先佇列相似。本文先給出堆排序 然後對其中要點進行解釋,程式中的注釋已經很詳細了。接著,給出乙個應用對排序的程式設計題 華為筆試題 例項 從小標0開始存放資料,利用陣列實現大頂堆,從而實現堆排序。include using namespace std define elementtyp...