基数排序(桶排序) 不同方法

详细解释:算法导论/数据结构书

1.链式基数排序

//n个数,每个数有g个关键字
//排序:从最后的关键字开始到最前的关键字
//分配+收集
//每个关键字分配+收集需要n+n时间,而共有g个关键字,时间复杂度为O(2ng),效率很高。
//如果用数组,数据集中在一个区间,则区间的长度很长,另外的区间的内存浪费了。
//用链表可以解决这个问题,且数据不需要先后顺序,所以无必要非要用数组

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 //个数
  4 #define maxn 1000
  5 //数的范围 x~y
  6 #define x 0
  7 #define y 9
  8 //关键字个数
  9 #define g 3
 10
 11 //n个数,每个数有g个关键字
 12 //排序:从最后的关键字开始到最前的关键字
 13 //分配+收集
 14 //每个关键字分配+收集需要n+n时间,而共有g个关键字,时间复杂度为O(2ng),效率很高。
 15 //如果用数组,数据集中在一个区间,则区间的长度很长,另外的区间的内存浪费了。
 16 //用链表可以解决这个问题,且数据不需要先后顺序,所以无必要非要用数组
 17
 18 struct node
 19 {
 20     //关键字的值
 21     long key[g+1];
 22 }data[maxn+1];
 23 //next:下一个数的编号
 24 //front,rear:一个链表的首,尾数据的编号
 25 long next[maxn+1],front[y-x+1],rear[y-x+1];
 26
 27 int main()
 28 {
 29     long n,i,j,head,pos,value,t;
 30     scanf("%ld",&n);
 31     for (i=1;i<=n;i++)
 32         for (j=1;j<=g;j++)
 33             scanf("%ld",&data[i].key[j]);
 34     for (i=1;i<n;i++)
 35         next[i]=i+1;
 36     next[n]=0;
 37     head=1;
 38     //key i
 39     for (i=g;i>=1;i--)
 40     {
 41         //值为j的链表的首地址,0代表j链表没有元素
 42         for (j=x;j<=y;j++)
 43             front[j]=0;
 44         pos=head;
 45         ///分配
 46         while (pos)
 47         {
 48             //把一个数添加到value链表的末尾
 49             value=data[pos].key[i];
 50             //如果原来value链表有元素,则原来value链表的末尾元素的后继为第pos个数
 51             //如果原来value链表没有元素,则value链表的起始元素为第pos个数
 52             if (front[value]!=0)
 53                 next[rear[value]]=pos;
 54             else
 55                 front[value]=pos;
 56             //当前value链表的末尾元素为第pos个数
 57             rear[value]=pos;
 58             pos=next[pos];
 59         }
 60         ///收集
 61         //把x链表,x+1链表,……,y链表 连接起来,而k链表的最后一个元素的后继为k+1链表的第一个元素
 62         value=x;
 63         while (front[value]==0)
 64             value++;
 65         head=front[value];
 66         while (value<=y)
 67         {
 68             t=value+1;
 69             while (front[t]==0 && t<=y)
 70                 t++;
 71             if (t==y+1)
 72                 break;
 73             next[rear[value]]=front[t];
 74             value=t;
 75         }
 76         next[rear[value]]=0;
 77     }
 78     printf("\n");
 79     pos=head;
 80     while (pos)
 81     {
 82         for (i=1;i<=g;i++)
 83             printf("%ld ",data[pos].key[i]);
 84         printf("\n");
 85         pos=next[pos];
 86     }
 87     return 0;
 88 }
 89 /*
 90 input:
 91 10
 92 1 1 2
 93 9 7 9
 94 3 8 5
 95 1 3 3
 96 5 4 3
 97 6 8 5
 98 2 1 3
 99 1 4 5
100 9 1 1
101 5 1 3
102 output:
103 1 1 2
104 1 3 3
105 1 4 5
106 2 1 3
107 3 8 5
108 5 1 3
109 5 4 3
110 6 8 5
111 9 1 1
112 9 7 9
113 */

2.基数排序+排序

//n个数,每个数有g个关键字
//可以在一次基数排序(桶排序)后,结合其它排序
//适用于:2~3个关键字,第一个关键字的范围较大,且分布较为分散,
    //通过第一个关键字把数分成若干个区间后,区间的大小较小,从而每个区间的排序时间也较小

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 //个数
  4 #define maxn 1000
  5 //数的范围 x~y
  6 #define x 0
  7 #define y 9
  8 //关键字个数
  9 #define g 3
 10
 11 //n个数,每个数有g个关键字
 12 //可以在一次基数排序(桶排序)后,结合其它排序
 13 //适用于:2~3个关键字,第一个关键字的范围较大,且分布较为分散,
 14     //通过第一个关键字把数分成若干个区间后,区间的大小较小,从而每个区间的排序时间也较小
 15
 16 struct node
 17 {
 18     //关键字的值
 19     long key[g+1];
 20 }data[maxn+1],f[maxn+1];
 21 //next:下一个数的编号
 22 //front,rear:一个链表的首,尾数据的编号
 23 long next[maxn+1],front[y-x+1],rear[y-x+1];
 24
 25 void qsort_(long l,long r)
 26 {
 27     long i,j,p,q;
 28     struct node t;
 29     i=l; j=r; p=f[(l+r)>>1].key[2]; q=f[(l+r)>>1].key[3];
 30     while (i<=j)
 31     {
 32         while (f[i].key[2]<p || (f[i].key[2]==p && f[i].key[3]<q)) i++;
 33         while (f[j].key[2]>p || (f[j].key[2]==p && f[j].key[3]>q)) j--;
 34         if (i<=j)
 35         {
 36             t=f[i];
 37             f[i]=f[j];
 38             f[j]=t;
 39             i++;
 40             j--;
 41         }
 42     }
 43     if (i<r) qsort_(i,r);
 44     if (j>l) qsort_(l,j);
 45 }
 46
 47 int main()
 48 {
 49     long n,i,j,head,pos,value,b;
 50     scanf("%ld",&n);
 51     for (i=1;i<=n;i++)
 52         for (j=1;j<=g;j++)
 53             scanf("%ld",&data[i].key[j]);
 54     for (i=1;i<n;i++)
 55         next[i]=i+1;
 56     next[n]=0;
 57     head=1;
 58     ///key 1
 59
 60     //值为j的链表的首地址,0代表j链表没有元素
 61     for (j=x;j<=y;j++)
 62         front[j]=0;
 63     pos=head;
 64     ///分配
 65     while (pos)
 66     {
 67         //把一个数添加到value链表的末尾
 68         value=data[pos].key[1];
 69         //如果原来value链表有元素,则原来value链表的末尾元素的后继为第pos个数
 70         //如果原来value链表没有元素,则value链表的起始元素为第pos个数
 71         if (front[value]!=0)
 72             next[rear[value]]=pos;
 73         else
 74             front[value]=pos;
 75         //当前value链表的末尾元素为第pos个数
 76         rear[value]=pos;
 77         pos=next[pos];
 78     }
 79     ///收集
 80     printf("\n");
 81     j=0;
 82     for (i=x;i<=y;i++)
 83         if (front[i]!=0)
 84         {
 85             b=j+1;
 86             pos=front[i];
 87             while (pos!=rear[i])
 88             {
 89                 j++;
 90                 f[j]=data[pos];
 91                 pos=next[pos];
 92             }
 93             j++;
 94             f[j]=data[pos];
 95             qsort_(b,j);
 96         }
 97     for (i=1;i<=n;i++)
 98     {
 99         for (j=1;j<=g;j++)
100             printf("%ld ",f[i].key[j]);
101         printf("\n");
102     }
103     return 0;
104 }
105 /*
106 input:
107 10
108 1 1 2
109 9 7 9
110 3 8 5
111 1 3 3
112 5 4 3
113 6 8 5
114 2 1 3
115 1 4 5
116 9 1 1
117 5 1 3
118 output:
119 1 1 2
120 1 3 3
121 1 4 5
122 2 1 3
123 3 8 5
124 5 1 3
125 5 4 3
126 6 8 5
127 9 1 1
128 9 7 9
129 */

3.从前到后依次对关键字排序(不推荐)

//n个数,每个数有g个关键字
//如果从最前的关键字开始到最后的关键字排序,则需要sort(p,q,w) data[x]~data[y]排第w个关键字,
    //然后延伸出sort(s,t,w+1) [p<=s<=t<=q]
//该方法耗费大量时间和内存,不推荐

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 //个数
  4 #define maxn 1000
  5 //数的范围 x~y
  6 #define x 0
  7 #define y 9
  8 //关键字个数
  9 #define g 3
 10
 11 //n个数,每个数有g个关键字
 12 //如果从最前的关键字开始到最后的关键字排序,则需要sort(p,q,w) data[x]~data[y]排第w个关键字,
 13     //然后延伸出sort(s,t,w+1) [p<=s<=t<=q]
 14 //该方法耗费大量时间和内存,不推荐
 15
 16 struct node
 17 {
 18     //关键字的值
 19     long key[g+1];
 20 }data[maxn+1],f[maxn+1];
 21 //next:下一个数的编号
 22 //front,rear:一个链表的首,尾数据的编号
 23
 24 void sort(long p,long q,long w)
 25 {
 26     long i,j,head,pos,value,next[maxn+1],front[y-x+1],rear[y-x+1],b[y+1],e[y+1];
 27     for (i=p;i<q;i++)
 28         next[i]=i+1;
 29     next[q]=0;
 30     head=p;
 31     //值为j的链表的首地址,0代表j链表没有元素
 32     for (j=x;j<=y;j++)
 33         front[j]=0;
 34     pos=head;
 35     ///分配
 36     while (pos)
 37     {
 38         //把一个数添加到value链表的末尾
 39         value=data[pos].key[w];
 40         //如果原来value链表有元素,则原来value链表的末尾元素的后继为第pos个数
 41         //如果原来value链表没有元素,则value链表的起始元素为第pos个数
 42         if (front[value]!=0)
 43             next[rear[value]]=pos;
 44         else
 45             front[value]=pos;
 46         //当前value链表的末尾元素为第pos个数
 47         rear[value]=pos;
 48         pos=next[pos];
 49     }
 50     ///收集
 51     for (i=p;i<=q;i++)
 52         f[i]=data[i];
 53     j=p-1;
 54     for (i=x;i<=y;i++)
 55         if (front[i]!=0)
 56         {
 57             b[i]=j+1;
 58             pos=front[i];
 59             while (pos!=rear[i])
 60             {
 61                 j++;
 62                 data[j]=f[pos];
 63                 pos=next[pos];
 64             }
 65             j++;
 66             data[j]=f[pos];
 67             e[i]=j;
 68         }
 69     if (w!=g)
 70     {
 71         for (i=x;i<=y;i++)
 72             //没有数或者只有1个数就不用排了
 73             if (front[i]!=0 && b[i]!=e[i])
 74                 sort(b[i],e[i],w+1);
 75     }
 76 }
 77
 78 int main()
 79 {
 80     long i,j,n;
 81     scanf("%ld",&n);
 82     for (i=1;i<=n;i++)
 83         for (j=1;j<=g;j++)
 84             scanf("%ld",&data[i].key[j]);
 85     sort(1,n,1);
 86     printf("\n");
 87     for (i=1;i<=n;i++)
 88     {
 89         for (j=1;j<=g;j++)
 90             printf("%ld ",data[i].key[j]);
 91         printf("\n");
 92     }
 93     return 0;
 94 }
 95 /*
 96 input:
 97 10
 98 1 1 2
 99 9 7 9
100 3 8 5
101 1 3 3
102 5 4 3
103 6 8 5
104 2 1 3
105 1 4 5
106 9 1 1
107 5 1 3
108 output:
109 1 1 2
110 1 3 3
111 1 4 5
112 2 1 3
113 3 8 5
114 5 1 3
115 5 4 3
116 6 8 5
117 9 1 1
118 9 7 9
119 */

题目:

题目13基数排序的实现(学时:3)
A为每个关键字不超过3位的十进制整数关键字集合,试编写一个采用静态链表组织模式实现的基数排序程序将A进行由小到大的排序。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 //个数
  4 #define maxn 1000
  5 //数的范围 x~y
  6 #define x 0
  7 #define y 9
  8 //关键字个数
  9 #define g 3
 10
 11 //n个数,每个数有g个关键字
 12 //排序:从最后的关键字开始到最前的关键字
 13 //分配+收集
 14 //每个关键字分配+收集需要n+n时间,而共有g个关键字,时间复杂度为O(2ng)。
 15 //如果用数组,数据集中在一个区间,则区间的长度很长,另外的区间的内存浪费了。
 16 //用链表可以解决这个问题,且数据不需要先后顺序,所以无必要非要用数组
 17
 18 struct node
 19 {
 20     //关键字的值
 21     long key[g+1];
 22 }data[maxn+1];
 23 //next:下一个数的编号
 24 //front,rear:一个链表的首,尾数据的编号
 25 long next[maxn+1],front[y-x+1],rear[y-x+1];
 26
 27 int main()
 28 {
 29     char c;
 30     long n,i,j,head,pos,value,t;
 31     scanf("%ld",&n);
 32     for (i=1;i<=n;i++)
 33     {
 34         c=getchar();
 35         for (j=1;j<=g;j++)
 36         {
 37             c=getchar();
 38             data[i].key[j]=c-48;
 39         }
 40
 41     }
 42     for (i=1;i<n;i++)
 43         next[i]=i+1;
 44     next[n]=0;
 45     head=1;
 46     //key i
 47     for (i=g;i>=1;i--)
 48     {
 49         //值为j的链表的首地址,0代表j链表没有元素
 50         for (j=x;j<=y;j++)
 51             front[j]=0;
 52         pos=head;
 53         ///分配
 54         while (pos)
 55         {
 56             //把一个数添加到value链表的末尾
 57             value=data[pos].key[i];
 58             //如果原来value链表有元素,则原来value链表的末尾元素的后继为第pos个数
 59             //如果原来value链表没有元素,则value链表的起始元素为第pos个数
 60             if (front[value]!=0)
 61                 next[rear[value]]=pos;
 62             else
 63                 front[value]=pos;
 64             //当前value链表的末尾元素为第pos个数
 65             rear[value]=pos;
 66             pos=next[pos];
 67         }
 68         ///收集
 69         //把x链表,x+1链表,……,y链表 连接起来,而k链表的最后一个元素的后继为k+1链表的第一个元素
 70         value=x;
 71         while (front[value]==0)
 72             value++;
 73         head=front[value];
 74         while (value<=y)
 75         {
 76             t=value+1;
 77             while (front[t]==0 && t<=y)
 78                 t++;
 79             if (t==y+1)
 80                 break;
 81             next[rear[value]]=front[t];
 82             value=t;
 83         }
 84         next[rear[value]]=0;
 85     }
 86     printf("\n");
 87     pos=head;
 88     while (pos)
 89     {
 90         for (i=1;i<=g;i++)
 91             printf("%ld",data[pos].key[i]);
 92         printf("\n");
 93         pos=next[pos];
 94     }
 95     return 0;
 96 }
 97 /*
 98 input:
 99 10
100 112
101 979
102 385
103 133
104 543
105 685
106 213
107 145
108 911
109 513
110 output:
111 112
112 133
113 145
114 213
115 385
116 513
117 543
118 685
119 911
120 979
121 */
时间: 2024-10-05 09:26:31

基数排序(桶排序) 不同方法的相关文章

基数排序/桶排序-单链表实现

今天下午编程实现了基数排序(桶排序),只能说一千个人有一千个哈姆雷特,因此,一千个人可能有一千种基数排序的实现方式,无论是用数组,栈,队列,单链表(都是线性表哦, 好巧,哈哈).重要的是理解该排序算法的思路后,自己也就可以尝试着慢慢写出来了.时间关系,暂且只给出跟人代码(面试黄金月),以后有机会再补充实现思路.新手出道,代码可读性不要期望太高,多包涵,相信以后自己会进步的. typedef struct listnode // 定义节点 { int data; struct listnode *

---------快排-----表排-----基数排序(桶排序)-----

其思想就是  在  一堆数字里面找一个  枢纽数字   然后将数字分成了两堆      ,   一个大于该数字,一个小于该数字.  然后去递归的治理   最后合并一下就OK了. ---------------附上一个极为简陋的代码------------------- // 依然是 递归实现~~~好恶心. void Quicksort( ElementType A[], int N ) { if(N<2) return; pivot = 从A[] 中选一个主元; //主元选择的要恰当. 将S =

基数排序与桶排序,计数排序【详解】

桶排序简单入门篇^-^ 在我们生活的这个世界中到处都是被排序过的东东.站队的时候会按照身高排序,考试的名次需要按照分数排序,网上购物的时候会按照价格排序,电子邮箱中的邮件按照时间排序……总之很多东东都需要排序,可以说排序是无处不在.现在我们举个具体的例子来介绍一下排序算法. 首先出场的是我们的主人公小哼,上面这个可爱的娃就是啦.期末考试完了老师要将同学们的分数按照从高到低排序.小哼的班上只有5个同学,这5个同学分别考了5分.3分.5分.2分和8分,哎,考得真是惨不忍睹(满分是10分).接下来将分

有Leetcode中一道题,谈桶排序,基数排序和计数排序

几种非比较排序 在LeetCode中有个题目叫Maximum Gap,是求一个非排序的正数数列中按顺序排列后的最大间隔.这个题用桶排序和基数排序都可以实现.下面说一下桶排序.基数排序和计数排序这三种非比较排序. 桶排序 这种排序的主要思想是,把数列分配到多个桶中,然后再在各个桶中使用排序算法进行排序,当然也可以继续使用桶排序. 假设数组的最大值是A,最小值是B,长度是L,则每个桶的大小可以是S=Max(1,(A-B)/(L-1))则可以分为(A-B)/S+1个桶. 对于数列中的数字x,用(x-B

桶排序/基数排序(Radix Sort)

说基数排序之前,我们先说桶排序: 基本思想:是将阵列分到有限数量的桶子里.每个桶子再个别排序(有可能再使用别的排序算法或是以递回方式继续使用桶排序进行排序).桶排序是鸽巢排序的一种归纳结果.当要被排序的阵列内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n)).但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响.          简单来说,就是把数据分组,放在一个个的桶中,然后对每个桶里面的在进行排序. 例如要对大小为[1..1000]范围内的n个整数A[1..n]排序 首

【排序】基数排序(计数排序、桶排序)

在此对于桶排序做出两种方法: 一.简化版桶排序 代码如下: <span style="font-size:18px;">/*简化版的桶排序*/ #include <stdio.h> int main() { int book[1001],i,j,t,n; for(i=0;i<=1000;i++) { book[i]=0; } scanf("%d",&n);//输入一个数n,表示接下来有n个数 for(i=1;i<=n;i+

桶排序和基数排序

桶排序的基本思想 假设有一组长度为N的待排关键字序列K[1....n].首先将这个序列划分成M个的子区间(桶) .然后基于某种映射函数 ,将待排序列的关键字k映射到第i个桶中(即桶数组B的下标 i) ,那么该关键字k就作为B[i]中的元素(每个桶B[i]都是一组大小为N/M的序列).接着对每个桶B[i]中的所有元素进行比较排序(可以使用快排).然后依次枚举输出B[0]....B[M]中的全部内容即是一个有序序列. 假如待排序列K= {49. 38 . 35. 97 . 76. 73 . 27.

算法导论-- 线性时间排序(计数排序、基数排序、桶排序)

线性时间排序 前面介绍的几种排序,都是能够在复杂度nlg(n)时间内排序n个数的算法,这些算法都是通过比较来决定它们的顺序,这类算法叫做比较排序 .下面介绍的几种算法用运算去排序,且它们的复杂度是线性时间. -------------------------------------- 1.计数排序 计数排序采用的方法是:对每个元素x,去确定小于x的元素的个数,从而就可以知道元素x在输出数组中的哪个位置了. 计数排序的一个重要性质是它是稳定的,即对于相同的两个数,排序后,还会保持它们在输入数组中的

基于非比较的排序:计数排序(countSort),桶排序(bucketSort),基数排序(radixSort)

计数排序 条件:要排序的数组的元素必须是在一定范围的,比如是1~100.在排序之前我们必须知道数组元素的范围. 思路:顾名思义:就是用一个数组来计数的. 步骤: 1.用一个数组来计数count[ ],将要排序的数组arr[ ]的元素记为数组count[ ]数组的下标,如果数组arr[]中有两个数相同就在count[]++.如count[arr[i]]++. 2. 再一次遍历数组count[ ],将count[i]  +=  count[i-1]+count[i-2]+....+count[0],