16. 数据结构进阶十六排序实现之基数排序

16. 数据结构进阶十六排序实现之基数排序

“社会犹如一条船 , 每人都要有掌舵的准备。--易卜生”

我们来看下基数排序。

 

 

1.  基数排序

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

           基数排序不需要进行记录关键字间的比较。基数排序是 一种借助多关键字排序的思想对逻辑关键字进行排序的方法。

基数排序是通过“分配”和“收集”过程来实现排序。

假设有欲排数据序列如下所示:

73  22  93  43 55  14  28  65  39  81

首先根据个位数的数值,在遍历数据时将它们各自分配到编号0至9的桶(个位数值与桶号一一对应)中。

分配结果(逻辑想象)如下图所示:

分配结束后。接下来将所有桶中所盛数据按照桶号由小到大(桶中由顶至底)依次重新收集串起来,得到如下仍然无序的数据序列:

81  22  73  93 43  14  55  65  28  39

接着,再进行一次分配,这次根据十位数值来分配(原理同上),分配结果(逻辑想象)如下图所示:

分配结束后。接下来再将所有桶中所盛的数据(原理同上)依次重新收集串接起来,得到如下的数据序列:

14 22  28  39  43  55  65  73  81  93

观察可以看到,此时原无序数据序列已经排序完毕。如果排序的数据序列有三位数以上的数据,则重复进行以上的动作直至最高位数为止。

 

 

 

2.  代码实现

主要部分代码:

首先申请一个存放基数的空间,空间大小为元素个数大小总和。

           初始化倍数基数为1. 

           处理第一次循环的时候,基数为10 (即nRadixBase).

           将处理的数组放入到nDataRadix中(获取元素中的其中一个值)。

           nDataRadix[i]= nPData[i] % nRadixBase;

           nDataRadix[i] /= nRadixBase / 10;

           然后调用RadixCountSort函数进行分配。

处理基数为100,处理百位的数。以此循环。

 

 

最后释放申请的辅助空间。

最后如下图1:

2.1      RadixCountSort

分配保存计数的个数的数组(个数由所调函数传入)pnCount。

分配保存存放零时的排序结果的数组pnSort。                            

初始化个数数组pnCount。

pnCount记录数据各元素当前处理位拥有的数量。

处理前数组:{73,22,93, 43,55,14,28,65, 39, 81};

npIndex数组(即元素的余数数组):3 ,2,3,3,5,4,8,5,9,1

当第一轮处理完毕后

余数为0:

余数为1:81

余数为2:22

余数为3:73 93 43

余数为4:14

余数为5:55 65

余数为6:

余数为7:

余数为8:28

余数为9:39

pnCount :0,1,2,5,6,8,8,8,9,10

处理完毕后得到数组:81,22,73,93,43,14,55,65,28,39

按照个位数大小进行了排序。

将一轮处理完的数组赋值给最后的数组。

最后释放pnSort,pnCount

3.  源码

#include<stdio.h>

#include<stdlib.h>

#defineN10

int RadixCountSort(int* npIndex, intnMax, int* npData, intnLen)

{

    int*pnCount  = (int*)malloc(sizeof(int)*nMax);        //保存计数的个数

    inti=0;

 

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

    {

       pnCount[i] = 0;

    }

    for(i = 0; i < nLen; ++i)    //初始化计数个数

    {

       ++pnCount[npIndex[i]];

    }

 

    for(i = 1; i < 10; ++i)  //确定不大于该位置的个数。

    {

       pnCount[i] += pnCount[i - 1];

    }

 

    int *pnSort  = (int*)malloc(sizeof(int)* nLen);   //存放零时的排序结果。

 

    //注意:这里i是从nLen-10的顺序排序的,是为了使排序稳定。

    for(i = nLen - 1; i >= 0; --i)

    {

       --pnCount[npIndex[i]];       

       pnSort[pnCount[npIndex[i]]] = npData[i];

    }

 

    for(i = 0; i < nLen; ++i)        //把排序结构输入到返回的数据中。

    {

        npData[i]= pnSort[i];

    }

   free(pnSort);                       //记得释放资源。

    free(pnCount);

    return1;

}

 

//基数排序

int RadixSort(int* nPData, intnLen)

{

    //申请存放基数的空间

    int*nDataRadix    = (int*)malloc(sizeof(int)* nLen);

 

    intnRadixBase = 1;    //初始化倍数基数为1

    intnIsOk = 0; //设置完成排序为false

    inti;

    //循环,知道排序完成

    while(nIsOk==0)

    {

        nIsOk= 1;

       nRadixBase *= 10;

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

        {

           nDataRadix[i] = nPData[i] %nRadixBase;

           nDataRadix[i] /= nRadixBase / 10;

            if(nDataRadix[i] > 0)

            {

               nIsOk = 0;

            }

        }

        if(nIsOk==1)        //如果所有的基数都为0,认为排序完成,就是已经判断到最高位了。

        {

            break;

        }

       RadixCountSort(nDataRadix, 10, nPData, nLen);

    }

 

   free(nDataRadix);

 

    return1;

}

int main(intargc,char *argv[])

{

    inti=0;

    intj;

           j = N;

           intnData[N]={73,22,93, 43, 55,14,28,65, 39, 81};

   RadixSort(nData, j);

 

    printf("基数排序法排序后:\n");

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

    {

       printf("%d ", nData[i]);

    }

    printf("\n");

    return0;

}

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值