基数排序_FAFU_1270

来源:互联网 发布:excel数据统计方法 编辑:程序博客网 时间:2024/06/16 01:00

基数排序的介绍:

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;}