【转】基数排序

转自:http://www.cppblog.com/shongbee2/archive/2009/04/24/80992.html

 

今天学了基数排序,据说他的时间复杂度也是O(n),他的思路就是:
没有计数排序那么理想,我们的数据都比较集中,都比较大,一般是4,5位。基本没有小的数据。
那我们的处理很简单,你不是没有小的数据嘛。我给一个基数,例如个位,个位都是[0-10)范围内的。先对他进行归类,把小的放上面,大的放下面,然后个位排好了,在来看10位,我们也这样把小的放上面,大的放下面,依次内推,直到最高位排好。那么不就排好了吗?我们只需要做d(基数个数)的循环就可以了。时间复杂度相当于O(d * n) 因为d为常量,例如5位数,d就是5.所以近似为O(n)的时间复杂度。这次自己写个案例:

最初的数据

排好个位的数据

排好十位的数据

排好百位的数据

981

981

725

129

387

753

129

387

753

955

753

456

129

725

955

725

955

456

456

753

725

387

981

955

456

129

387

981

这里只需循环3次就出结果了。

<!--[if !supportLists]-->3.       <!--[endif]-->但是注意,我们必须要把个位排好。但是个位怎么排呢?这个是个问题。书上说的是一叠一叠的怎么合并,我是没有理解的。希望知道的有高手教我一下。

我是用的一个计数排序来排各位的,然后排十位。效率应该也低不到哪里去。呵呵。。

思路就这样咯。奉上源代码:

 

#include <stdio.h>
#include <stdlib.h>

// 计数排序,npRadix为对应的关键字序列,nMax是关键字的范围。npData是具体要
// 排的数据,nLen是数据的范围,这里必须注意npIndex和npData对应的下标要一致
// 也就是说npIndex[1] 所对应的值为npData[1]
int RadixCountSort( int* npIndex,  int nMax,  int* npData,  int nLen)
{
     // 这里就不用说了,计数的排序。不过这里为了是排序稳定
    
// 在标准的方法上做了小修改。

     int* pnCount  = ( int*)malloc( sizeof( int)* nMax);         // 保存计数的个数
     for ( int i = 0; i < nMax; ++i)
    {
        pnCount[i] = 0;
    }
     for ( int i = 0; i < nLen; ++i)     // 初始化计数个数
    {
        ++pnCount[npIndex[i]];
    }

     for ( int i = 1; i < 10; ++i)   // 确定不大于该位置的个数。
    {
        pnCount[i] += pnCount[i - 1];
    }

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

    
// 注意:这里i是从nLen-1到0的顺序排序的,是为了使排序稳定。
     for ( int i = nLen - 1; i >= 0; --i)
    {
        --pnCount[npIndex[i]];        
        pnSort[pnCount[npIndex[i]]] = npData[i];
    }

     for ( int i = 0; i < nLen; ++i)         // 把排序结构输入到返回的数据中。
    {
        npData[i] = pnSort[i];
    }
    free(pnSort);                         // 记得释放资源。
    free(pnCount);
     return 1;
}

// 基数排序
int RadixSort( int* nPData,  int nLen)
{
     // 申请存放基数的空间
     int* nDataRadix    = ( int*)malloc( sizeof( int) * nLen);

     int nRadixBase = 1;     // 初始化倍数基数为1
     bool nIsOk =  false// 设置完成排序为false

    
// 循环,知道排序完成
     while (!nIsOk)
    {
        nIsOk =  true;
        nRadixBase *= 10;
         for ( int i = 0; i < nLen; ++i)
        {
            nDataRadix[i] = nPData[i] % nRadixBase;
            nDataRadix[i] /= nRadixBase / 10;
             if (nDataRadix[i] > 0)
            {
                nIsOk =  false;
            }
        }
         if (nIsOk)         // 如果所有的基数都为0,认为排序完成,就是已经判断到最高位了。
        {
             break;
        }
        RadixCountSort(nDataRadix, 10, nPData, nLen);
    }

    free(nDataRadix);

     return 1;
}

int main()
{
     // 测试基数排序。
     int nData[10] = {123,5264,9513,854,9639,1985,159,3654,8521,8888};
    RadixSort(nData, 10);
     for ( int i = 0; i < 10; ++i)
    {
        printf("%d ", nData[i]);
    }
    printf("\n");

    system("pause");
     return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值