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


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

    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("
    ");
     79     pos=head;
     80     while (pos)
     81     {
     82         for (i=1;i<=g;i++)
     83             printf("%ld ",data[pos].key[i]);
     84         printf("
    ");
     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("
    ");
     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("
    ");
    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("
    ");
     87     for (i=1;i<=n;i++)
     88     {
     89         for (j=1;j<=g;j++)
     90             printf("%ld ",data[i].key[j]);
     91         printf("
    ");
     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("
    ");
     87     pos=head;
     88     while (pos)
     89     {
     90         for (i=1;i<=g;i++)
     91             printf("%ld",data[pos].key[i]);
     92         printf("
    ");
     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 */
  • 相关阅读:
    exit() _exit() 函数区别
    Linux-进程间通信(五): 网络套接字
    Linux-进程间通信(六): 记录锁
    Linux-进程间通信(N): 各种IPC的使用场景
    SQL EXISTS
    日志格式化
    logminer实战之生产环境写入数据字典,dg环境查询拷贝日志,测试环境进行挖掘,输出结果
    awr脚本使用dump导出导入
    logminer使用测试库进行挖掘分析,10.2.0.5
    10.2.0.5环境dg测试logminer挖掘日志分析
  • 原文地址:https://www.cnblogs.com/cmyg/p/6818817.html
Copyright © 2020-2023  润新知