在簡單選擇排序中,我們每一趟都要選擇乙個極值元素。那麼在第一趟選擇極值元素時,能否多做些工作,為後面選擇極值元素帶來便利呢?下面介紹一下堆排序。
首先看一下什麼是堆:
滿足下列性質的序列稱為堆:
小頂堆:
ri <= r2i;
ri <= r(2i+1)
如:大頂堆:
ri >= r2i;
ri >= r(2i+1).
如:堆的性質:小頂堆對應的完全二叉樹任意結點均比孩子小或相等。大頂堆對應的完全二叉樹中任意結點均比其孩子大或相等。
小頂堆堆頂元素最小,大頂堆堆頂最大,子樹也是堆。
基本思想:利用堆每次選擇出最大交換到隊尾。
輸入:順序表的長度,順序表中各個元素。
輸出:排好序的順序表中各個元素。
執行結果:
具體方法:
先建初始大頂堆;
堆頂與堆尾互換(最大記錄換到最後);忽略堆尾,將前n-1個記錄組成的樹重新調整為大頂堆(篩選)。
重複上一步n-1趟 即可。
輔助巨集:
#define ok 1
#define error 0
#define true 1
#define false 0
#define overflow -1
#define null 0
typedef char *infotype;
typedef int keytype; //設關鍵字為整型
順序表儲存結構定義:
typedef struct
redtype;
//順序表的儲存結構定義
typedef struct
sqlist;
首先我們來看一下如何篩選:
篩選即對一顆左/右子樹均為堆的完全二叉樹,調整根結點使整個二叉樹也稱為乙個堆。
方法:備份堆頂,比較堆頂與其兩個孩子,若堆頂不最大則將兩孩子中的大者上移,之後的子樹可能不再是堆。重複上述操作至最後(當前堆頂大於等於孩子或無孩子)。
typedef sqlist heaptype; //採用順序表儲存堆
void heapadjust(heaptype &h,int s,int m)
}//經此迴圈則比rc大的均上移 ,s指向待插入位置
redcopy(h.r[s],rc);
}
建造初始大頂堆:從最後乙個非葉子結點開始向根結點方向逐步調整建堆。
完整實現:
void heapsort(heaptype &h)
}
演算法分析:
最壞時間複雜度:o(n*logn)
選出最大的乙個,比選擇排序慢,為啥還好呢?
建初始大頂堆比簡單選擇排序慢了,複雜度變成了o(n*logn)。但是,構造的樹在後面提高了找極值元素的效率。
僅用乙個記錄輔助空間rc
該演算法是一種不穩定的演算法。優化餘地小。
正序時最慢,適合n大且雜亂。
堆排序 堆排序優化 索引堆排序
堆排序 堆排序優化 索引堆排序 注 堆排序 索引堆排序 都是不穩定的排序。注 索引最大堆排序有誤!有沒有大神可以指點一二?1 堆 所有元素 都從索引0開始 父親結點索引 i 左孩子結點索引 2i 1 右孩子結點索引 2i 2 左後乙個非葉子結點索引 n 1 2 用於構建堆,從最後乙個非葉子結點索引開...
堆排序 堆排序優化 索引堆排序
堆排序 堆排序優化 索引堆排序 注 堆排序 索引堆排序 都是不穩定的排序。注 索引最大堆排序有誤!有沒有大神可以指點一二?1 堆 所有元素 都從索引0開始 父親結點索引 i 左孩子結點索引 2i 1 右孩子結點索引 2i 2 左後乙個非葉子結點索引 n 1 2 用於構建堆,從最後乙個非葉子結點索引開...
堆排序 模擬堆排序
838.堆排序 輸入乙個長度為n的整數數列,從小到大輸出前m小的數。輸入格式 第一行包含整數n和m。第二行包含n個整數,表示整數數列。輸出格式 共一行,包含m個整數,表示整數數列中前m小的數。資料範圍 1 m n 1051 m n 105,1 數列中元素 1091 數列中元素 109 輸入樣例 5 ...