算法-基数排序(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 著;王刚,邹恒明,殷建平,王宏志等译