36排序算法之基数排序

排序算法之基数排序

基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。 

 

原理:用整理扑克牌的例子说明基本原理。

 

示例

(1)整数排序

将整数(元素)看成多元组(数字串)

每个分量(一位)有m(10)种不同的取值(0,1,2,3,…)

编号为0,1,2,…,m-1元素的有序次序===多元组的“字典次序”。

 

 

(2)字符串排序

例如,将英文单词排成字典次序:

for  end  else  goto  file  int  new  case  char  and

长度不足4个字母的单词尾部加空格符 □。

 

 

 

算法的实现:

(1)选用的数据结构

1)数据采用链式存储,总队列queue

2)结点值域为数组a[k],每个分量a[j]满足

    0≤a[j]的序号值≤m-1(j=0,2,…,k-1)

3)m个分队列用于分组q[0],q[1],q[2],…,q[m-1]。

 

(2)算法描述

步骤1)置分量下标j等于k-1

步骤2)[分组]

①将各分队列q[0],q[1],q[2],…,q[m-1]置空。

②依次从总队列中取下元素a,设其第j个分量a[j]的序号值为t,将该元素放在分队列q[t]的尾部,反复如此,直到把总队列中元素取完。

步骤3)[收集]按分队列的序号由小到大,依次将分队列q[0],q[1],q[2],…,q[m-1]首尾相接,组成新的总队列。

步骤4)j=j-1,若j<0,排序结束;否则,转步骤2。

 

 

基数排序实现算法:

 

(1)类型定义

typedef  struct  node  //定义结点类型

  { char  a[k];       //值域和分量类型

    struct  node  *next; // 链域

  } *ptr;     // 指针类型名

 

(2)实现程序

void radix_sort(ptr &h,int k)

   {

 int i,j,y;

 char x;    

ptr p;

     struct  {ptr head,tail;}  q[m];

 for(j=k-1;j>=0;j- -)

     { 

 for(i=0;i<m;i++)

 q[i].head=NULL;

    while(h)

       {

  x=h->a[j]; 

        y=value(x);   //将x换算成序号值

        if(q[y].head==NULL)

q[y].head=h; 

       else

 q[y].tail->next=h;

                 q[y].tail=h;

h=h->next;//取总队列下一个元素

       }  //分组完毕

         i=0;

   while(q[i].head==NULL)

 i++; 

   h=q[i].head;

   p=q[i].tail;  

   for(i++;i<m;i++)

      if(q[i].head)

p->next=q[i].head,p=q[i].tail;

   p->next=NULL;

      }

   }

 

源代码:
#include<math.h>
testBS()
{
    inta[] = {2, 343, 342, 1, 123, 43, 4343, 433, 687, 654, 3};
    int *a_p = a;
    //计算数组长度
    intsize = sizeof(a) / sizeof(int);
    //基数排序
    bucketSort3(a_p, size);
    //打印排序后结果
    inti;
    for(i = 0; i < size; i++)
    {
        printf("%d\n", a[i]);
    }
    intt;
    scanf("%d", t);
}
//基数排序
voidbucketSort3(int *p, intn)
{
    //获取数组中的最大数
    intmaxNum = findMaxNum(p, n);
    //获取最大数的位数,次数也是再分配的次数。
    intloopTimes = getLoopTimes(maxNum);
    inti;
    //对每一位进行桶分配
    for(i = 1; i <= loopTimes; i++)
    {
        sort2(p, n, i);
    }
}
//获取数字的位数
intgetLoopTimes(intnum)
{
    intcount = 1;
    inttemp = num / 10;
    while(temp != 0)
    {
        count++;
        temp = temp / 10;
    }
    returncount;
}
//查询数组中的最大数
intfindMaxNum(int *p, intn)
{
    inti;
    intmax = 0;
    for(i = 0; i < n; i++)
    {
        if(*(p + i) > max)
        {
            max = *(p + i);
        }
    }
    returnmax;
}
//将数字分配到各自的桶中,然后按照桶的顺序输出排序结果
voidsort2(int *p, intn, intloop)
{
    //建立一组桶此处的20是预设的根据实际数情况修改
    intbuckets[10][20] = {};
    //求桶的index的除数
    //如798个位桶index=(798/1)%10=8
    //十位桶index=(798/10)%10=9
    //百位桶index=(798/100)%10=7
    //tempNum为上式中的1、10、100
    inttempNum = (int)pow(10, loop - 1);
    inti, j;
    for(i = 0; i < n; i++)
    {
        introw_index = (*(p + i) / tempNum) % 10;
        for(j = 0; j < 20; j++)
        {
            if(buckets[row_index][j] == NULL)
            {
                buckets[row_index][j] = *(p + i);
                break;
            }
        }
    }
    //将桶中的数,倒回到原有数组中
    intk = 0;
    for(i = 0; i < 10; i++)
    {
        for(j = 0; j < 20; j++)
        {
            if(buckets[i][j] != NULL)
            {
                *(p + k) = buckets[i][j];
                buckets[i][j] = NULL;
                k++;
            }
        }
    }
}

 

 

 

 

posted @ 2018-03-05 16:55  gd_沐辰  阅读(356)  评论(0编辑  收藏  举报