基数排序
说基数排序,其实就是多次的桶排,不过,这里只需要十个桶,基数排序基于多关键字,拿一个数256来说,它被分为各位,十位,百位,每位都是一个关键字,而且关键字的范围都
是在0-9的范围内;
先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数,和百位数;
以下是一个待排序数列:278-》109-》063-》930-》589-》184-》505-》269-》008-》083-》
1.按个位关键字排序,如图:
最后一行就是按个位桶排的序列。
2.按十位关键字排序,(一定是在1排序的序列基础上再按十位排序,目的是:如果十位相同,由于个位排好序,所以再入桶的时候,还是有序的),如图:
结果:
3.百位排序:排序序列基于2中排好的序列;
最终排序结果就出来了,下面用代码说话:
/*
*基数排序
*/
#pragma once
#define MAXSIZE 1000
int getdigit(int x, int d)
{
int a[] = { 1, 1, 10, 100}; //最大三位数,所以这里只要百位就满足了。
return (x / a[d]) % 10;
}
//打印
void PrintArr(int ar[], int n)
{
for (int i = 0; i < n; ++i)
{
cout << ar[i] << " ";
}
cout << endl;
}
void lsdradix_sort(int arr[], int begin, int end, int d)
{
const int radix = 10;
int count[radix], i, j;
int *bucket = (int*)malloc((end - begin + 1)*sizeof(int)); //所有桶的空间开辟
//按照分配标准依次进行排序过程
for (int k = 1; k <= d; ++k)
{
//置空
for (i = 0; i < radix; i++)
{
count[i] = 0;
}
//统计各个桶中所盛数据个数
for (i = begin; i <= end; i++)
{
count[getdigit(arr[i], k)]++;
}
//count[i]表示第i个桶的右边界索引
for (i = 1; i < radix; i++)
{
count[i] = count[i] + count[i - 1];
}
//把数据依次装入桶(注意装入时候的分配技巧)
for (i = end; i >= begin; --i) //这里要从右向左扫描,保证排序稳定性
{
j = getdigit(arr[i], k); //求出关键码的第k位的数字, 例如:576的第3位是5
bucket[count[j] - 1] = arr[i]; //放入对应的桶中,count[j]-1是第j个桶的右边界索引
--count[j]; //对应桶的装入数据索引减一
}
//注意:此时count[i]为第i个桶左边界
//从各个桶中收集数据
for (i = begin, j = 0; i <= end; ++i, ++j)
{
arr[i] = bucket[j];
}
}
free(bucket);
}
void main()
{
int br[10] = { 278, 109, 63, 930, 589, 184, 505, 269, 8, 83 };
cout << "原数据如下:" << endl; PrintArr(br, 10);
lsdradix_sort(br, 0, 9, 3); //3位数
cout << "排序后数据如下:" << endl;
PrintArr(br, 10);
}
赐教!