基数排序的介绍:
http://baike.baidu.com/view/1170573.htm
基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。
以LSD为例,假设原来有一串数值如下所示: 73, 22, 93, 43, 55, 14, 28, 65, 39, 81 首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中: 0 1 81 2 22 3 73 93 43 4 14 5 55 65 6 7 8 28 9 39 接下来将这些桶子中的数值重新串接起来,成为以下的数列: 81, 22, 73, 93, 43, 14, 55, 65, 28, 39 接着再进行一次分配,这次是根据十位数来分配: 0 1 14 2 22 28 3 39 4 43 5 55 6 65 7 73 8 81 9 93 接下来将这些桶子中的数值重新串接起来,成为以下的数列: 14, 22, 28, 39, 43, 55, 65, 73, 81, 93 这时候整个数列已经排序完毕;如果排序的对象有三位数以上,则持续进行以上的动作直至最高位数为止。 LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好。MSD的方式与LSD相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中。
fafu1270:http://acm.fafu.edu.cn/problem.php?id=1270
这题 如果仅仅是过那很简单了,用queue直接排两次就能过,根本不用什么循环~~~ (不过不是老师的本意 - -#,管他呢,先过了再说 ……^_^)
// http://acm.fafu.edu.cn/problem.php?id=1270
#include <stdio.h>
#include <queue>
using namespace std;
int num[30005];
int main(void)
{
queue<int> que[10];
int n;
scanf("%d", &n);
int val;
int temp = n;
int i;
//刚读进来时就把数据按个位大小存到0~9队列中
while(temp--)
{
scanf("%d", &val);
que[val%10].push(val);
}
//然后把队列中的数据首尾相连存到num数组中去
int index=0;
for(i=0; i<10; i++)
{
while(!que[i].empty())
{
num[index++] = que[i].front();
que[i].pop();
}
}
//最后按输入数据的十位再次存放到0~9队列中
for(i=0; i<n; i++)
{
que[num[i]/10%10].push(num[i]);
}
int foo=0;
//然后把队列中的经过两次收集之后的数据打印出来
for(i=0; i<10; i++)
{
while(!que[i].empty())
{
foo++;
printf("%d%s", que[i].front(), foo%10==0 ? "\n": " ");
que[i].pop();
}
}
return 0;
}
然后,把上面代码改动一下,让其可以处理更多的情况,也可以实现真正的排序,只要给radix适当的值就行了,当然,还是比较低级的,不能算是实用的基数排序算法
// http://acm.fafu.edu.cn/problem.php?id=1270
#include <stdio.h>
#include <queue>
using namespace std;
int num[30005];
queue<int> que[10];
void radix_sort(int * array, int radix, int n)
{
// radix是要排的位数, 比如说把一堆数按个位和十位排两次,那radix=2
// n是num数组中元素的个数
int j;
int k=1; // k is an important variable, can't used by others
for(int i=1; i<=radix; i++) //对radix扫描:个位,十位,百位……
{
//把所有的数按某一位放入队列数组中
for(j=0; j<n; j++)
que[array[j]/k%10].push(array[j]);
k *= 10;
//把所有数据首尾相连后再次放入数组中去
j = 0;
for(int i=0; i<10; i++) //扫描队列数组
{
while(!que[i].empty())
{
array[j++] = que[i].front();
que[i].pop();
}
}
}
}
int main(void)
{
int n,i;
scanf("%d", &n);
//把数据读到数组中去
for(i=0; i<n; i++)
scanf("%d", &num[i]);
radix_sort(num, 2, i);
//打印出排序后的数据
for(i=0; i<n; i++)
printf("%d%s", num[i], (i+1)%10==0 ? "\n" : " ");
return 0;
}
版本三:
可以不用指定位数来进行排序了
#include <stdio.h>
#include <queue>
using namespace std;
int num[30005];
queue<int> que[10];
void radix_sort(int * array, int length)
{
int j;
int k=1;
bool scan_over = false;
while(true) //对radix扫描:个位,十位,百位……
{
if(scan_over)
break;
scan_over = true;
//把所有的数按某一位放入队列数组中
for(j=0; j<length; j++)
{
if(array[j]/k != 0)
scan_over = false;
que[array[j]/k%10].push(array[j]);
}
k *= 10;
//把所有数据首尾相连后再次放入数组中去
j = 0;
for(int i=0; i<10; i++) //扫描队列数组
{
while(!que[i].empty())
{
array[j++] = que[i].front();
que[i].pop();
}
}
if(!scan_over)
printf("k is %d\n", k);
}
}
int main(void)
{
int n,i;
scanf("%d", &n);
//把数据读到数组中去
for(i=0; i<n; i++)
scanf("%d", &num[i]);
radix_sort(num, i);
//打印出排序后的数据
for(i=0; i<n; i++)
printf("%4d%s", num[i], (i+1)%10==0 ? "\n" : " ");
return 0;
}

本文深入探讨了基数排序的概念,包括LSD和MSD两种排序方式,并通过具体实例展示了如何实现基数排序算法。此外,文章还提供了一个简单的C++代码示例,用于解决特定问题,并介绍了改进版的基数排序算法,使其能够处理更多情况。

1327

被折叠的 条评论
为什么被折叠?



