算法-基数排序(radix sort)

本文由@呆代待殆原创,转载请注明出处。

 

简介:这个排序是原来用在卡片排序机上的一个算法,一般用来比较具有多对关键字域的记录,如日期(年月日),通过基数排序我们会依次对年月日这三个关键字进行排序,只要对每个关键字进行排序的算法是稳定的,那么最后输出的序列就一定是正确的。

 

思路:基数排序思路很简单,首先取第一个关键字,然后对其进行排序,在第一次排序的基础上取第二个关键字,再对其进行排序,直到遍历完所有的关键字,一般用计数排序实现基数排序。

 

算法分析

时间复杂度:Θ(i*x)  i 是关键码的数量,x是用于关键码排序的算法的时间复杂度,如果基于计数排序则为Θ(i(n+k)) 。

空间复杂度:Θ(2n+k) n是排序数组的规模,k是关键码能取的值的数量。

稳定性:稳定算法

是否是原址排序:否

 

代码实现

 1 vector<int> radix_sort(vector<int> radix, int i){//i是关键码的数量也就是最大数的位数
 2     if (i < 1){
 3         cout << "error" << endl;
 4         return radix;
 5     }
 6     vector<int> count;//用来计数,借用计数排序实现基数排序
 7     vector<int> temp;//用来储存临时的目前要比较的位数的值
 8     vector<int> out;//临时记录每一趟的排序结果
 9     count.resize(10, 0);//这个的大小应该是关键码的取值范围
10     out.resize(10, 0);//这个的大小应该和radix一样
11     temp.resize(10, 0);//这个的大小应该和radix一样
12 
13     for (int n = 1; n <= i; ++n){
14         for (int &n : count)//将count置为0
15             n = 0;
16 
17         int tn = 0;//取出本次要比的关键码
18         for (int a : radix){
19             for (int k = n; k > 1; --k)
20                 a /= 10;
21             temp[tn++] = a % 10;
22 
23         }
24 
25         for (int n : temp)//记录相同的元素的个数。
26             ++count[n];
27 
28         for (int i = 1; i < count.size(); ++i)//计算小于等于n的数,同时它把自己也算了进去
29             count[i] = count[i] + count[i - 1];
30         int a = 9;
31         for (auto n = temp.rbegin(); n!=temp.rend();++n){//把每一个元素摆到正确的位置,因为比n小的数的个数已经存到count里了,所以可以直接用
32             out[count[*n] - 1] = radix[a--];//减一的原因是因为count记录的是小于等于元素 n 的数,其中包括 n 自己,所以要剪掉一位
33             --count[*n];
34         }
35         radix = out;
36     }
37     return radix;
38 }

 

 

参考资料:《算法导论 中文版》(英文版第三版)(美)ThomasH.Cormen,CharlesE.Leiserson,RonaldL.Rivest,CliffordStein 著;王刚,邹恒明,殷建平,王宏志等译

posted @ 2016-04-21 17:13  呆代待殆  阅读(571)  评论(0编辑  收藏  举报