基数排序是基于桶式排序的变种,主要是为了通过多次遍历减少空间占用(效果相当显著)。其思路可以描述为:
1.首先待排序的序列要满足基数排序的特征,比如有“基数”的概念(整数和字符串都可以套用)
2.建立一个大小为“基数”的数组,数组每个元素是一个队列(为了节省空间应该使用链表实现)
3.根据序列的“位数”决定遍历的次数m,每次遍历相当于按某一位做桶式排序。重复的元素push到队列中。
4.m次遍历后排序完成,最后一次遍历输出结果。因为数据不是按线性结构存储。
下面是我的实现,采用vector<list>结构:
1 #include<iostream> 2 #include<list> 3 #include<vector> 4 5 using namespace std; 6 7 /* 8 * N is the input intergers 9 * B is base 10 * W is the intergers's max width 11 */ 12 void buildvector(vector<list<int> >&arr,int B) 13 { 14 int cnt; 15 int num; 16 cout<<"input count of numbers to be sorted"<<endl; 17 cin>>cnt; 18 for(int i=0;i<cnt;++i) 19 { 20 cout<<"input num["<<i+1<<"]:"; 21 cin>>num; 22 arr[num%B].push_back(num); 23 } 24 } 25 void radixsort(vector<list<int> >&arr,int B,int W) 26 { 27 vector<list<int> > brr(B); 28 for(int k=2;k<=W;++k) 29 { 30 int BS=B; 31 for(int j=2;j<k;++j) BS*=B; 32 for(int i=0;i<B;++i) 33 { 34 while(!arr[i].empty()) 35 { 36 int x=arr[i].front(); 37 brr[x/BS%B].push_back(x); 38 arr[i].pop_front(); 39 } 40 } 41 swap(arr,brr); 42 } 43 } 44 void show(vector<list<int> >&arr) 45 { 46 vector<list<int> >::iterator itv=arr.begin(); 47 while(itv!=arr.end()) 48 { 49 list<int>::iterator it=itv->begin(); 50 while(it!=itv->end()) 51 { 52 cout<<*it<<' '; 53 ++it; 54 } 55 ++itv; 56 } 57 cout<<endl; 58 } 59 60 int main() 61 { 62 vector<list<int> > arr(16); 63 buildvector(arr,16); 64 radixsort(arr,16,3); 65 show(arr); 66 }
注意几点:
1.每次遍历之后实际上要借助原始数组输出,以便下次遍历可以直接递归。我这里偷懒用了个swap操作。
2.时间复杂度=(O(N)+O(基数))*O(位数)
3.也可以不借助链表,仅用数组实现。每次遍历前预处理序列,找到遍历的时候每一位将会重复的元素个数,计算出该位在数组中的起始下标即可。