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

2021-08-19 20:35:00 字數 1876 閱讀 4437

歸併排序利用了分治思想(將原問題分解成若干類似於原問題的子問題,遞迴對子問題求解,然後合併子問題的解得到原問題的解)進行排序。

分解: 分解待排序序列,把n個記錄不斷二分直到分成單個記錄。

解決: merge對子序列排序。

合併: 合併已經排好序的序列。

整個排序過程如圖:

歸併排序在合併的時候是比較兩個子串行的第乙個元素,選較小的那個放入臨時陣列,然後指標前移,繼續比較兩個子串行的第乙個元素,直到某個序列插入完畢,把另乙個序列的剩餘元素插入到臨時陣列,當完成最後一組二分子序列的排序的時候,整個序列排序完畢。原始碼:

void merge(vectorlist, int start, int middle, int end, vectortmp)

while (i <= middle)

while (j <= end)

for (k = 0; k <= (end - start); k++)

list[start + k] = tmp[k];

}void mergesort(vectorlist, vectortmp, int start, int end)

}

基數排序屬於分配排序。分配排序的思想是:不靠比較關鍵字來排序,而是通過空間使其時間複雜度達到線性階o(n),簡單的說就是以空間換時間。

在說基數排序之前先說一下同為分配排序的桶排序。比如現在有8個數,那麼我們需要9個桶,即乙個9位的陣列,初值為0,遍歷待排序序列,每出現一次桶計數加一,最後遍歷輸出這個陣列,計數為幾輸幾次,可以看出當資料的大小跨度非常大的時候,需要申請的陣列空間也會變得非常大。

基數排序相當於乙個多維的桶排序,他以位數為關鍵字,比如同樣對範圍[0,50]的序列排序,需要用到51個桶,而基數排序只需要[0,9]10個桶,分別個位十位用兩次。我們用乙個例子說明一下基數排序的排序過程:

比如我們現在有乙個無序序列

1) 按個位數對序列排序:

2222, 1234, 4356, 278, 19

19, 2222, 1234, 4356, 278

3) 按百位排:

19, 2222, 1234, 278, 4356

4) 按千位排:

19, 278, 1234, 2222, 4356

基數排序的時間複雜度是o(d*(n+r)),其中d是位數,r是基數,n是序列個數。因為不存在比較的操作,所以最好最壞情況都是這個。

原始碼:

//求陣列中數的最大位數以確定迴圈次數

int maxbit(vectorlist)

} return d;

}void radixsort(vectorlist)

//針對radix看list中元素對應位數字是幾就在對應計數器加一

for (int j = 0; j < list.size(); j++)

//確定這幾個桶中元素在此次排序中實際應該在的位置

for (int j = 1; j < list.size(); j++)

//從後往前存tmp是因為每個桶中可能不止乙個元素,之前是從前往後統計的count所以這裡要從後往前

//因為放棄比較,所以使用count的計數來作為判斷大小的依據

for (int j = list.size() - 1; j >= 0; j--)

//把排好序的tmp再賦值給原陣列

for (int j = 0; j < list.size(); j++)

radix *= 10;

}}

各種排序不為人知的真相

常用的排序演算法有 交換排序 氣泡排序 快速排序 選擇排序 直接選擇排序 堆排序 插入排序 直接插入排序 二分插入排序 希爾排序 歸併排序 基數排序 直接選擇排序和氣泡排序的比較 void bubblesort vector list void choosesort vector list swap...

不為人知的NodeJS 1

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

百度不為人知的API

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