桶排序、基數排序、計數排序

參考鏈接:https://blog.csdn.net/qq_19446965/article/details/81517552

桶排序

  • 首先求出最大值最小值,把此區間劃分爲k個區間(即k個桶),再分別對桶內元素進行排序,將桶內元素合併得到排序結果。
  • 假設數據均勻分佈,每個桶內元素爲 n/k 個,並對桶內元素通過快排排序,每次排序複雜度爲O(n/k log(n/k)),總的時間複雜度爲O(n) + O(k)*O(n/k log(n/k))=O(n) + O(n log(n/k)),當k接近n時,複雜度可以認爲是 O(n)
  • 桶排序的複雜度與建桶的效果緊密相連,常見的建桶思路爲將最大值最小值之間的區間平分,或桶的個數爲 2^n,10^n
  • 分治思想

基數排序

  • 非比較算法
  • 將所有待排整數統一爲位數相同的整數(常見的爲非負整數,對代碼稍作修改,負整數也可通過基數排序進行排序)
  • 從最低位或最高位開始一次進行穩定排序,完成之後整個序列即爲一個有序序列

計數排序

  • 以空間換時間
  • 遍歷數組統計每個數出現的次數,根據統計結果寫回數組
  • 是一種特殊的桶排序,當桶的個數最大時,桶排序即爲計數排序

複雜度比較

//d爲k進制下最長的位數

代碼實現

代碼實現思路與:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

基本一致

//sort
#include<iostream>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;

void bucketSort(vector<int> &arr){
	//將min和max等分成n份
	int low=999999999;
	int high=-999999999;
	for(int i=0;i<arr.size();i++){
		low=min(low,arr[i]);
		high=max(high,arr[i]);
	} 
	int size=(high-low)/10+1;  //一個桶的區間大小 
	vector<int> bucket[10];
	for(int i=0;i<arr.size();i++){
		int index=(arr[i]-low)/size;
		bucket[index].push_back(arr[i]); 
	}
	for(int i=0;i<10;i++){
		int bsize=bucket[i].size();
		sort(bucket[i].begin(),bucket[i].end());	
	}
	int index=0;
	for(int i=0;i<10;i++){
		for(int j=0;j<bucket[i].size();j++){
			arr[index]=bucket[i][j];
			index++;
		}
	}
}

//基數排序 
//從低位開始排序 
void redixSort(vector<int> &arr){
	int maxx=-999999999;
	for(int i=0;i<arr.size();i++){
		maxx=max(maxx,arr[i]);  //獲取最大值 
	}
	int exp=10;
	while(maxx/exp!=0){
		exp*=10;  //獲取最大值的位數 
	}
	vector<int> bucket[10]; 
	int exp2=10;
	while(exp2<=exp){
		for(int i=0;i<arr.size();i++){
			bucket[(arr[i]%exp2)/(exp2/10)].push_back(arr[i]); //放到對應的桶中 
		}
		int index=0;
		for(int i=0;i<10;i++){
			for(int j=0;j<bucket[i].size();j++){
				arr[index]=bucket[i][j];
				index++;
			}
			bucket[i].clear();    //因爲桶是重複使用的,所以在一輪結束之後注意將桶清空 
		}
		exp2*=10;
	}
}

//考慮負數,從低位開始排序 
//將桶的大小擴展到20個即可 
void redixSortp(vector<int> &arr){
	int maxx=-999999999;
	for(int i=0;i<arr.size();i++){
		maxx=max(maxx,arr[i]);  //獲取最大值 
	}
	int exp=10;
	while(maxx/exp!=0){
		exp*=10;  //獲取最大值的位數 
	}
	vector<int> bucket[20];  
	int exp2=10;
	while(exp2<=exp){
		for(int i=0;i<arr.size();i++){
			bucket[(arr[i]%exp2)/(exp2/10)+10].push_back(arr[i]); //放到對應的桶中 
		}
		int index=0;
		for(int i=0;i<20;i++){
			for(int j=0;j<bucket[i].size();j++){
				arr[index]=bucket[i][j];
				index++;
			}
			bucket[i].clear();    //因爲桶是重複使用的,所以在一輪結束之後注意將桶清空 
		}
		exp2*=10;
	}
}

void countSort(vector<int>& arr){
	int maxx=-999999999;
	int minn=999999999;
	for(int i=0;i<arr.size();i++){
		maxx=max(maxx,arr[i]);
		minn=min(minn,arr[i]);
	}
	int size=maxx-minn+1;
	int count[size]={0};
	for(int i=0;i<arr.size();i++){
		count[arr[i]-minn]++;
	}
	int index=0;
	for(int i=0;i<size;i++){
		for(int j=0;j<count[i];j++){
			arr[index]=i+minn;
			index++;
		}
	}
} 

int main(){
	int a[20]={45,95,23,78,21,2,5,0,-69,5,9,159,87,65,25,-56,56,56,57,100};
	vector<int> arr(a,a+20);
//	bucketSort(arr);
	redixSortp(arr);
//	countSort(arr);
	for(int i=0;i<20;i++){
		cout<<arr[i]<<" ";
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章