0
点赞
收藏
分享

微信扫一扫

数据结构与算法系列----基数排序


基数排序与其他的排序方法都不同,它不需要比较关键字的大小。

算法的时间复杂度是O(n). 相比于快速排序的O(nlgn),从表面上看具有不小的优势.但事实上可能有些出入,因为基数排序的n可能具有比较大的系数K.因此在具体的应用中,应首先对这个排序函数的效率进行评估.

它是根据关键字中各位的值,通过对排序的N个元素进行若干趟“分配”与“收集”来实现排序的。 


 


不妨通过一个具体的实例来展示一下,基数排序是如何进行的。 


设有一个初始序列为: R {50, 123, 543, 187, 49, 30, 0, 2, 11, 100}。


我们知道,任何一个阿拉伯数,它的各个位数上的基数都是以0~9来表示的。


所以我们不妨把0~9视为10个桶。 


我们先根据序列的个位数的数字来进行分类,将其分到指定的桶中。例如:R[0] = 50,个位数上是0,将这个数存入编号为0的桶中。

数据结构与算法系列----基数排序_基数排序

分类后,我们在从各个桶中,将这些数按照从编号0到编号9的顺序依次将所有数取出来。
这时,得到的序列就是个位数上呈递增趋势的序列。 
按照个位数排序: {50, 30, 0, 100, 11, 2, 123, 543, 187, 49}。
接下来,可以对十位数、百位数也按照这种方法进行排序,最后就能得到排序完成的序列。


代码实现:

#include<iostream>

using namespace std;

/* 获取x这个数的d位数上的数字,比如获取123的1位数,结果返回3 */
int GetDigit(int x,int d)
{
int a[] = { 1, 1, 10, 100 }; //本实例中的最大数是百位数,所以只要到100就可以了
return (x / a[d]) % 10;
}

/* 参数含义分别为:待排序数组;待排序数组首元素下标;待排序数组末元素下标;数组元素最大的位数,此处假设最大是百位数(3位数) */
void RadixSort(int arry[], int begin, int end, int digitLen)
{
int radix = 10; // 基数
int i = 0, j = 0;
int *count = new int[radix]; // 存放各个桶的数据统计个数
int *assit = new int[end - begin + 1];

// 按照从低位到高位的顺序执行排序过程
for (int d = 1; d <= digitLen; d++)
{

// 置空各个桶的数据统计
for (i = 0; i < radix; i++)
count[i] = 0;


// 统计各个桶将要装入的数据个数
for (i = begin; i <= end; i++)
{
j = GetDigit(arry[i], d);
count[j]++;
}

// count[i]表示第i个桶的右边界索引
for (i = 1; i < radix; i++)
count[i] = count[i] + count[i - 1];


// 将数据依次装入桶中
// 这里要从右向左扫描,保证排序稳定性
for (i = end; i >= begin; i--)
{
j = GetDigit(arry[i], d); // 求出关键码的第k位的数字, 例如:576的第3位是5
assit[count[j] - 1] = arry[i]; //放入对应的桶中,count[j]-1是第j个桶的右边界索引
count[j]--; // 对应桶的装入数据索引减一
}

// 将已分配好的桶中数据再倒出来,此时已是对应当前位数有序的表
for (i = begin, j = 0; i <= end; i++, j++)
arry[i] = assit[j];

}

delete[]count;
delete[]assit;
}


int main()
{
int arry[] = { 50, 123, 543, 187, 49, 30, 0, 2, 11, 100 };

int len = sizeof(arry) / sizeof(int);

RadixSort(arry, 0, len - 1, 3);

for (int i = 0; i < len; i++)
cout << arry[i] << " ";
cout << endl;

return 0;
}





返回目录---->​​数据结构与算法目录​​



举报

相关推荐

0 条评论