說起堆排序就不得先說下簡單選擇排序,畢竟都是選擇排序類,堆排序也是對選擇排序的一種改進。
選擇排序我的理解就是每趟找出某位置應該放的記錄。直接上**,拿**感受吧:
void main()
; int len = sizeof(arr)/sizeof(arr[0]);
for(int i=0;i是不是感覺就是每趟找出i位置應該放的記錄。它與初始狀態下待排序的記錄序列的排列情況無關。因為不管怎麼樣,都是去挨個遍歷找最小下標,然後放到該趟應該放的位置。所以它的時間複雜度為o(n*2)。在交換的過程中某些相同的記錄可能會順序變化,所以它是一種不穩定的排序。
那麼堆排序是怎麼實現的的呢,在我看來堆排序無非就是建立大(小)根堆,然後進行不斷地調整,調整的過程就是一種選擇排序的過程,先上張粗圖感受下如何建立大根堆吧:
它是從第乙個非葉子節點開始調整的,找出他的左右孩子節點中的最大值,然後將其交換,交換之後繼續從最大的孩子節點中執行相同操作,直到滿足條件:所有的非葉子節點都比它左右孩子節點的值大。
來來來,上**感受:
void swap(int *x, int *y)
static void heapadjust(int *arr, int start, int len)
swap(&arr[0], &arr[len - 1]); //頂堆元素和最後乙個元素交換
//2.堆調整
for (int k = len - 1; k>1; k--) //
}
堆調整就是自頂向下不斷地對堆進行調整,交換堆頂和堆底最後乙個元素,繼續調整,,,
來分析下堆排序的複雜度:
(1)可以看出它主要複雜到建立初始堆和堆調整過程中的反覆篩選上。分析堆排序對原始記錄的排序狀態並不敏感,無論是好是壞它的平均時間複雜度均為o(n*logn)。
(2)空間複雜度,幾乎可以不考慮,有沒有發現上面的堆調整函式還存在小瑕疵,,,,沒錯,在比較的過程中發現其左右孩子比它自身大的時候,直接進行交換,這樣可能交換的次數會很多,所以可以考慮用乙個臨時變數把初始的arr[start]記錄,最後只進行一次交換。看下面**:
static void heapadjust(int *arr, int start, int len)
{ int tmp;
tmp = arr[start];
for (int i = start * 2 + 1; i還有最後一點:堆排序的比較和交換是跳躍式的,所以它是一種不穩定的排序,其次,在建立初始堆的所需比較的次數較多,它不適合待排序序列個數較少的情況。
堆排序 堆排序優化 索引堆排序
堆排序 堆排序優化 索引堆排序 注 堆排序 索引堆排序 都是不穩定的排序。注 索引最大堆排序有誤!有沒有大神可以指點一二?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 ...