算法就是这么一回事(排序)(第五部分)

八、基数排序

  它是这样实现的:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

  基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。

  

基数排序的时间复杂度是 O(k·n),其中n是排序元素个数,k是数字位数。注意这不是说这个时间复杂度一定优于O(n·log(n)),k的大小取决于数字位的选择(比如比特位数),和待排序数据所属数据类型的全集的大小;k决定了进行多少轮处理,而n是每轮处理的操作数目。

以排序n个不同整数来举例,假定这些整数以B为底,这样每位数都有B个不同的数字,k = logB(N),N是待排序数据类型全集的势。虽然有B个不同的数字,需要B个不同的桶,但在每一轮处理中,判断每个待排序数据项只需要一次计算确定对应数位的值,因此在每一轮处理的时候都需要平均n 次操作来把整数放到合适的桶中去,所以就有:

  • k 约等于 logB(N)

所以,基数排序的平均时间T就是:

T ~= logB(Nn

其中前一项是一个与输入数据无关的常数,当然该项不一定小于logn

如果考虑和边角排序进行对照,基数排序的形式复杂度虽然不一定更小,但由于不进行比较,因此其基本操作的代价较小,而且在适当选择的B之下,k一般不大于logn,所以基数排序一般要快过基于比较的排序,比如快速排序。(转自维基百科基数排序)

 1 #include <iostream>
 2 #include <iterator>
 3 #include <vector>
 4 #include <ctime>
 5 #include <random>
 6 #include <functional>
 7 #include <algorithm>
 8 using namespace std;
 9 int intSwap(int& a,int& b)
10 {
11     int intswaptemp=a;
12     a=b;
13     b=intswaptemp;
14     return 0;
15 }
16 /*-------------------------------------------
17 -----------------基数排序----------------------
18 ---------------------------------------------*/
19 int getbytefun(vector<int>& ivec)//获得位数
20 {
21     int p10=10;
22     int bit=1;//保存最大位数
23     for(auto p:ivec)
24     {
25         while(p>=p10)//10也是两位数
26         {
27             p10*=10;
28             ++bit;
29         }
30     }
31     return bit;
32 }
33 int RadixSort(vector<int> &ivec)
34 {
35     int maxbit=getbytefun(ivec);
36     int *ivectemp=new int[ivec.size()];//temp
37     int *count=new int[10];//计数器,统计(0,1,2,3,4,5,6,7,8,9)出现的次数
38     int i,j,k;
39     int radix=1;
40     for(i=1;i<=maxbit;i++)//进行maxbit次排序,因为有maxbit位需要处理
41     {
42         for(int j=0;j<10;j++)
43             count[j]=0;//清空count,并设定初始值为0
44         for(auto &p:ivec)
45         {
46             k=((p)/radix)%10;
47             count[k]++;//统计数据相同一位(例如都是第三位)某个数字出现的次数
48         }
49 
50         //--------------------------------------------------------------------------
51         for(j=1;j<10;j++)
52             count[j]=count[j-1]+count[j];//通过该算法处理使得每一位最小数字以上都至少为1,为后面左准备
53                                  //这一句也就是基数排序的核心了,
54         //-------------------------------------------------------------------------
55         for(j=ivec.size()-1;j>=0;j--)
56         {
57            k=(ivec[j]/radix)%10;//某一位字符
58            ivectemp[count[k]-1]=ivec[j];//按照各位上面定义来实现排序某一位功能
59            count[k]--;
60         }
61         for(j=0;j<ivec.size();j++)
62             ivec[j]=ivectemp[j];
63         radix*=10;
64     }
65     delete []ivectemp;
66     delete []count;
67     return 0;
68 }
69 int main()
70 {
71     clock_t start,end;
72     vector<int> ivec,copyivec;
73     srand(14);
74     for(int i=0;i<10000;i++)//10k
75         ivec.push_back((int)rand());
76     copyivec=ivec;
77     start=clock();
78     RadixSort(ivec);
79     end=clock();
80     for(int i=0;i<10000;i+=500)
81         cout<<ivec[i]<<'\t';
82     cout<<endl;
83     cout<<"the time  of 1 is "<<end-start<<endl;
84 
85     return 0;
86 }

详情请参考http://www.cnblogs.com/Braveliu/archive/2013/01/21/2870201.html

posted @ 2014-11-09 21:41  菜鸟也会飞  阅读(168)  评论(0编辑  收藏  举报