1. 程式人生 > >選擇排序之堆排序

選擇排序之堆排序

swa 小根堆 二叉樹 輸出 完全 意義 跳出循環 堆排 ++

/*
* 選擇排序之堆排序
* 按照完全二叉樹的順序存儲方式,建立一顆完全二叉樹
* 若是大根堆:l(i)>=l(2*i),l(i)>=l(2*i+1)
* 若是小根堆:l(i)<=l(2*i),l(i)<=(2*i+1)
* 此時,初始堆建成,接下來的工作是進行調整
* 調整的是從[n/2]~1。
* 針對大根堆:對於[n/2]處的元素,若其比左右孩子中的較大者小,進行交換
* 同理對於其他的
* void BuildHeap(ET a[],int len){
* for(int i=n/2;i>0;i--){
* AdjustDown(a[],i,len);
* }
* void AdjustDown(ET a[],int k,int len){
* a[0]=a[k];
* for(i=2*k;i<=len;i=i*2){
* if(i<len&&a[i]<a[i+1])
* i++;
* if(a[0]>a[i])
* break;//排序成功,跳出循環
* else{
* a[k]=a[i];//a[i]向上翻,反正a[k]的值已經賦出去了,有了本分
* k=i; //同時新的待排序的k就是i,要繼續向下繼續調整
* }
* }
* a[k]=a[0];//最終的位置
* }

* 下面要說的是完整的堆排序過程
* 在建成一個真正意義上的對之後,我們還需要將其輸出,這樣我們才能直觀的看到算法處理的結果
* 而堆排序的輸出,通常是輸出堆頂元素後,通常將堆底元素送入堆頂,但此時肯定是不滿足堆的性質的,
* 所以此時必要又要重新調整堆,待調整完畢後,在進行輸出,循環如此
* void HeapSort(ET a[],int len){
* BulidHeap(a,len);
* for(i=len;i>1;i--){
* print(a[1]);//輸出堆頂元素
* swap(a[len],a[1]);//將最後堆底元素換到堆頂
* AdjustDown(a,1,len-1);//輸出一個元素後,還剩len-1
*
* }
*
* }

堆排序的時間復雜度跟最終形成的樹形狀有關

建堆時間是O(n),之後進行n-1次的調整(在建造堆的時候有一半,而在輸出的時候又有一半?),每次調整的時間與樹的高度有關,那就是O(h),又因是完全二叉樹,所以最終的時間復雜度為O(nlogn)
*
* }
*/

選擇排序之堆排序