基本排序算法之2——基数排序radixsort

  基数排序是基于桶式排序的变种,主要是为了通过多次遍历减少空间占用(效果相当显著)。其思路可以描述为:

    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.也可以不借助链表,仅用数组实现。每次遍历前预处理序列,找到遍历的时候每一位将会重复的元素个数,计算出该位在数组中的起始下标即可。

posted @ 2013-06-04 11:36  mjwk  阅读(309)  评论(0)    收藏  举报