第三章:查詢與排序(下)----------- 3.21基數排序

Curtis_發表於2019-03-11

基數排序:

       基數排序過程無須比較關鍵字,而是通過“分配”和“收集”過程來實現排序,它的時間複雜度可達到線性階:O(n)。(ps:kN)。對於十進位制數來說,每一位的數在[0,9]之中,d位的數,則有d列。基數排序首先按低位有效數字進行排,然後逐次向上一位進行排序,直到最高位排序結束

 約定: 待排數字中沒有0,沒有負數(有負數,做一次轉換全部變為正數即可

演算法過程: 

(1)、假設有欲排資料序列如下所示:

73 22 93 43 55 14 28 65 39 81。

首先根據個位數的數值,在遍歷資料時將它們各自分配到編號0至9的桶(個位數值與桶號一一對應)中。

分配結果(邏輯想象)如下圖所示:

分配結束後。接下來將所有桶中所盛資料按照桶號由小到大(桶中由頂至底)依次重新收集串起來,得到如下仍然無序的資料序列:

81 22 73 93 43 14 55 65 28 39

(2)、接著,再進行一次分配,這次根據十位數值來分配(原理同上),分配結果(邏輯想象)如下圖所示:

分配結束後。接下來再將所有桶中所盛的資料(原理同上)依次重新收集串接起來,得到如下的資料序列:

14 22 28 39 43 55 65 73 81 93。

(3)以此類推……

如果排序的資料序列有三位數以上的資料,則重複進行以上的動作直至最高位數為止。

程式碼:

#include<iostream>
#include<cmath>
#include<vector> 
using namespace std;

/**********************************/ 
//函式宣告: 
void sort(int arr[],int d,int length);
void putInBucket(int data,int digitOn);
int getDigitOn(int src,int d);
/**********************************/

/***********************************/
//全域性變數:
vector<int> bucket[10];


//將陣列arr,按d這個位來分配和收集 
void sort(int arr[],int length){
	int d=1;//入桶依據的位初始化為1
	
	int maxn=arr[0];//陣列的最大值 
	for(int i=1;i<length;i++){
		maxn=max(maxn,arr[i]);
	} 
	
	int dNum=1; //最大值有多少位
	while(maxn/10!=0){
		dNum++;
		maxn/=10;
	}
		
	while(d<=dNum){
		//依據第二個引數入桶和出桶
		sort(arr,d++,length); 
	} 	
} 

// 過載的sort:將陣列arr, 按d這個位來分配和收集
void sort(int arr[],int d,int length){
	//全部入桶
	for(int i=0;i<length;i++){
		putInBucket(arr[i],getDigitOn(arr[i],d));
	} 
	
	//出桶 
	//每個桶中的元素依次壓入原陣列
	int k=0;
	for(int j=0;j<10;j++){
		while(bucket[j].size()){
			arr[k++]=bucket[j].front();
			bucket[j].erase(bucket[j].begin());  //比較巧妙,移除第一個元素!
		}
	}	
} 
 
//得到十進位制數src的第d位:
int getDigitOn(int src,int d){
	return src/(int)(pow(10,d-1))%10;
} 

void putInBucket(int data,int digitOn){  
	switch(digitOn){
		case 0:
			bucket[0].push_back(data);
			break;
		case 1:
			bucket[1].push_back(data);
			break;
		case 2:
			bucket[2].push_back(data);
			break;
		case 3:
			bucket[3].push_back(data);
			break;
		case 4:
			bucket[4].push_back(data);
			break;
		case 5:
			bucket[5].push_back(data);
			break;
		case 6:
			bucket[6].push_back(data);
			break;
		case 7:
			bucket[7].push_back(data);
			break;
		case 8:
			bucket[8].push_back(data);
			break;
		case 9:
			bucket[9].push_back(data);
			break;	
	}
		
}

int main(){
    
    int arr[]={18,13,17,26,29,38,31,69,51};
	int len=9;
	
	sort(arr,len);
    
    //列印結果:
	for(int i=0;i<len;i++){
		cout<<arr[i]<<" ";
	} 
    
	return 0;	
}

 得到十進位制數src的第d位(需背住):

 //得到十進位制數src的第d位:
int getDigitOn(int src,int d){
	return src/(int)(pow(10,d-1))%10;
} 

執行結果:

小結:

計數排序: 適用於小範圍資料;

桶排序:    適用於均勻分配的資料。

 

參考:lanqiao.coding.me

相關文章