八大排序之歸併 基數排序

2021-08-15 19:45:16 字數 3486 閱讀 1305

歸併排序:將兩個或兩個以上的有序表組合乙個新的有序表稱為「歸併」。先使每個子串行有序,再歸併使子串行段有序,最後得到完全有序的序列。

演算法思想:我們通常用遞迴實現,先把待排序區間[startindex,endindex]以中點二分,接著把左邊子區間排序,再把右邊子區間排序,最後把左區間和右區間用一次歸併操作合併成有序的區間[startindex,endindex]。

歸併過程:比較a[i]和b[j]的大小,若a[i]≤b[j],則將第乙個有序序列中的元素a[i]複製到r[k]中,並令i和k分別加上1;否則將第二個有序序列中的元素a[j]複製到r[k]中,並令j和k分別加上1,如此迴圈下去,直到其中乙個有序序列取完,然後再將另乙個有序序列中剩餘的元素複製到r中從下標k到下標endindex的單元。

如圖所示:

上半部分為2分法使資料為有序序列,下半部分為歸併有序序列操作,最後為完全有序。

示例**如下:(測試**自己寫)

c++ code 12

3456

78910

1112

1314

1516

1718

1920

2122

2324

2526

2728

2930

3132

3334

3536

3738

3940

4142

43void

merge(

int*arr, 

int*tmp, 

intstartindex, 

intmidindex, 

intendindex)//歸併操作

else

}while

(i != midindex + 1)

while

(j != endindex + 1)

for(

inti = startindex; i <= endindex; i++)

}void

guib(

int*arr, 

int*tmp, 

intstartindex, 

intendindex)//歸併排序}

注:測試只需在main函式中建立兩個陣列,呼叫guib函式即可。

時間複雜度:一趟歸併排序呼叫n/2h次演算法merge將arr【1..n】中前後相鄰且長度為h的有序段兩兩合併得到2h的有序段,並存放到tmp【1..n】中。整個歸併排序需要log2^n趟。所以需要移動操作2*2h*(n/2h)*log2^n=2log2^n;比較操作是(n/2h)*h*log2^n=n/2log2^n;此演算法時間複雜度為nlgn. 

空間複雜度:o(1)。

穩定性:每次歸併若元素相同,不改變前後順序,所以為穩定的。

續:非遞迴實現**

c++ code 12

3456

78910

1112

1314

1516

1718

1920

2122

2324

2526

2728

2930

3132

3334

3536

3738

3940

4142

4344

4546

4748

4950

5152

5354

5556

57#include

#include

void

mergesort(

int*arr, 

int*tmp, 

intlength)

while

(leftmin 

1&& rightmin 

while

(leftmin 

while

(rightmin 

for(

intj = leftmin; j <= rightmax; j++)}}

}#define

n 10

intmain()

;int

t[n];

mergesort(a, t, n);

for(

inti = 

0; i 

基數排序:又稱「桶排序」,通過鍵值的部分的資訊,將要排序的元素分配到某些「桶」中,以此達到排序的目的。

演算法思想:從最次位的關鍵字k^(d-1)起進行排序。然後再對高一位的關鍵字k^(d-2)進行排序,依次重複,直至對k^0進行排序後成為乙個有序序列。叫「最低位優先」,簡稱lsd法。

排序過程如圖所示:

**如下:

c++ code 12

3456

78910

1112

1314

1516

1718

1920

2122

2324

2526

2728

2930

3132

3334

3536

3738

3940

4142

4344

4546

4748

4950

5152

5354

//資料最大值的位數 即排序躺數 (543)3

intfindmaxfigure(

int*arr, 

intlen)

}int

count = 0;

dowhile

(max != 0);

return

count;

}//資料的位上的數字 (45 0)1、(54 1)5

intfindnums(

intnum, 

intfigure)

//根據資料每一位進行入桶和出桶操作

void

radix(

int*arr, 

intlen, 

intfigures)

;int

count[

10] = {};

for(

inti = 

0; i 

intk = 0;

for(

inti = 

0; i 

10; i++)}}

//基數排序(桶排序)

void

radixsort(

int*arr, 

intlen)}

注:測試只需在main函式中呼叫void radixsort(int *arr, int len)就行。

時間複雜度: 可知排序躺數為count次,入桶和出桶操作為n,賦值給原始陣列為r*n,r為基數。所以時間複雜度為 o(n(count+r))。

空間複雜度:輔助儲存陣列tmp、count,所以為o(r*n+r),r為基數。

穩定性:穩定。

八大排序之基數排序

個人部落格 建議先看排序綜述,傳送門 資料結構與演算法系列之一 八大排序綜述。基數排序 英語 radix sort 是一種非比較型整數排序演算法,其原理是將整數按位數切割成不同的數字,然後按每個位數分別比較。由於整數也可以表達字串 比如名字或日期 和特定格式的浮點數,所以基數排序也不是只能使用於整數...

八大排序之基數排序

開始研究基數排序,還以為很複雜呢,誰知道也挺簡單的,它是一種非比較的排序,首先找到最大的位數,也就是先確定裡面最大的數有幾位,依次對個位,十位,等進行排序,它的原理就是你在對個位的大小進行排序時,算了,還是放圖吧 個位排序 它已經出現了基本有序 相對於十位來說 如,142,157,142也就在157...

八大排序 基數排序

基數排序 將整形10進製按每位拆分,然後從低位到高位依次比較各個位。每次比較完進行排序,直到整個陣列有序 主要分為兩個過程 1 分配,先從個位開始,根據位值 0 9 分別放到0 9號桶中 比如53,個位為3,則放入3號桶中 2 收集,再將放置在0 9號桶中的資料按順序放到陣列中 重複 1 2 過程,...