各種排序不為人知的真相

2021-08-18 23:08:21 字數 3203 閱讀 2745

常用的排序演算法有:

交換排序(氣泡排序、快速排序)

選擇排序(直接選擇排序、堆排序)

插入排序(直接插入排序、二分插入排序、希爾排序)

歸併排序、

基數排序

直接選擇排序和氣泡排序的比較

void bubblesort(vector& list)

}void choosesort(vector& list)

} swap(list[i], list[minp]);

}}

兩種排序方法的平均和最壞時間複雜度是一樣的都是o(n2),氣泡排序的最好時間複雜度是o(n),直接選擇排序的最好時間複雜度也是o(n2)。一般來說選擇比冒泡效率高(單從時間複雜度來考慮是看不出來的),從上面**可以看出氣泡排序的交換操作在內層,而選擇排序在外迴圈中進行交換操作。冒泡的話如果不這麼頻繁交換則需要記錄座標(犧牲空間複雜度),還有一點就是可以檢測整個陣列是否已經有序,即當某次遍歷沒有發生任何交換的時候終止演算法。

插入排序:就是每步將乙個待排序的記錄,按順序插入到前面已經排好序的序列中。直接插入排序就是從後往前挨個比較,二分插入的話就是運用二分法將待排序記錄插入。

void insertsort(vectorlist)

}int binary_search(const vector& list, int start, int end, int list_i)

return start;

}void b_insertsort(vectorlist)

}}

希爾排序是一種分組插入排序,通過將增量逐漸減小將逆序記錄消除。

void shellsort(vectorlist)

list[j + num] = tmp;

} num /= 2;

}}

希爾排序是最先突破o(n2)的排序演算法的一批,排序的本質是消除逆序數,冒泡、直接插入排序等每次只能消除乙個,所以複雜度都是o(n2),而比較快的如快排、希爾、堆排都是交換比較遠的記錄,使得一次交換能夠消除乙個以上的逆序,只不過規則不同。

快速排序屬於交換排序,是氣泡排序的一種改進。基本思想是通過一趟排序將要排序的記錄分為兩個部分,然後分別運用快排進行排序。從顯式的感覺上看,快排的快的有道理的,快排有遠距離交換,他每掃一遍待排序序列都會更有序,大的小的分開在兩邊。

原始碼:

//遞迴版

int sort(vector& list, int low, int high)

list[low] = tmp;

return low;

}void quicksort(vector& list, int low, int high)

接下來到堆排序同志了,在這之前先介紹一下他的簡配版----樹形選擇排序,也叫錦標賽排序,基本思想就是錦標賽的晉級機制(8進4、半決賽、決賽)。

首先將待排序記錄兩兩比較,然後取較小的記錄繼續進行比較(這裡以公升序排列為例),這樣就會得到乙個有n個葉子節點的完全二叉樹,如圖:

然後開始第二階段,輸出根節點,即得到最終結果的第乙個記錄。這時從葉子節點找到和最小值相同的記錄,把這個記錄當成最大開始比較得到次小值,如圖:(按比賽的思想來說就是找出被他打敗的選手裡哪個更強)

重複第二階段可以完成排序。由於n個葉子節點的完全二叉樹的深度是log2n+1,所以每選一次需要進行log2n次比較,n個點的時間複雜度就是nlog2n;但是這種方法需要的輔助儲存空間多,而且有一些最大值多餘的比較。為了做一下優化,堆排序就誕生了。

堆排序剛開始也是構建乙個完全二叉樹,只不過這裡不會有重覆記錄了,即先按照初始序列自頂向下寫出來就好了,然後按需求(公升序還是降序)選擇調整成最大堆還是最小堆,這裡以降序構造最大堆為例進行說明。最小堆就是這棵樹的所有父節點都比自己的子節點大。

構造最大堆是從最後乙個非葉子節點開始,從右往左從下往上地調整。如圖,初始序列[16,7,3,20,17,8]

從3開始,3-8不滿足最大堆定義,交換。

7不滿足,將7和他最大子節點交換。

16不滿足,將16和20交換。

換完之後16不滿足,16和17交換。

最大堆生成:

第二階段:輸出堆頂元素,將堆頂元素和最後乙個元素交換,調整堆。

3和20交換,3/17/8不滿足,選8和17中較大的和3交換,此時3/7/16又不滿足了,繼續交換得到圖3,此時最大堆又出現了。

繼續重複操作,完成排序:

堆排序原始碼:

//堆調整

void heapadjust(vector& list, int s, int length)

//如果右兒子比較大,調整

if (srchild <= length && list[srchild] > list[maxtemp])

//如果有調整,交換list記錄maxtemp,s

if (list[maxtemp] != list[s])

}}//初建堆

void buildheap(vector& list)

}void heapsort(vectorlist)

}

一定要看哦!!!

各種排序不為人知的真相(二)

歸併排序利用了分治思想 將原問題分解成若干類似於原問題的子問題,遞迴對子問題求解,然後合併子問題的解得到原問題的解 進行排序。分解 分解待排序序列,把n個記錄不斷二分直到分成單個記錄。解決 merge對子序列排序。合併 合併已經排好序的序列。整個排序過程如圖 歸併排序在合併的時候是比較兩個子串行的第...

不為人知的NodeJS 1

2.filename變數與 dirname變數 3.事件機制 用於進行標準輸出流的輸出,即在控制台中顯示一行字串用於進行標準錯誤輸出流的輸出,即向控制台輸出一條錯誤資訊用於檢視乙個物件中的內容並且將物件的資訊輸出到控制台中 console.time 標記開始時間 console.timeend 標記...

百度不為人知的API

1count encode 1.wmadecode 2type 49684lrcid data result 其中的count值為1是說返回的是乙個,這個沒什麼用,接下來的東西就有用了,encode 裡的值是歌曲加密後的位址,加密只是對檔名加密的,我們需要的只是前面的路徑,也就是 這部分,然後複製d...