基数排序

来源:互联网 发布:中国经济的问题 知乎 编辑:程序博客网 时间:2024/05/23 00:04

基数排序(Radix Sorting)是一种与其他排序算法完全不同的排序方法,其他的排序算法都是通过关键字之间的比较和移动来完成的,而基数排序则不需要比较,而是采用一种多关键字的思想。

什么是多关键字的思想呢?
给定一组数据,我可以先按个位的大小对所有数进行排序,然后再按十位进行排序,一直到最高位,这样就可以使整组数据变得有效,这样从最低位开始的方法称为最低位优先(Least Significant Digit first)

反之,如果先从最高为的关键字开始,最后再比较最低位,则称之为最高位优先(Most Significant Digit first)

排序过程如下图:
这里写图片描述

经过一次放置和回收,得到的序列已经按个位有序了,接下来按照次低位再次进行放置和回收。
这里写图片描述

由此可以看出,如果一组序列中最大的数为两位数,则需要两次的分配和收集,整个分配收集的次数与最大数的位数有关。

求最大位数:

int GetMaxBit(int* array,int size){    assert(array);    int base = 10;    int digits = 1;//至少是个位数    for(int i = 0;i < size;++i)    {        while(array[i] >= base)//只要有数大于base,则位数+1        {            ++digits;            base *= 10;        }    }    return digits;}

基数排序需要两个辅助空间,一个是0~9号桶,另一个是计算定位的数组,定位数组是干什么的呢?就是记录每个桶中的数据待会要放回原数组的哪个位置。
这里写图片描述

下面是代码实现:

void RadixSort(int* array,int size){    assert(array);    int* buckets = new int[size];    int base = 1;    int maxbit = GetMaxBit(array,size);    for(int i = 0;i < maxbit;++i)    {        //统计0~9号桶中的个数        int counts[10] = {0};        for(int i = 0;i < size;++i)        {            int num = (array[i]/base)%10;            counts[num]++;        }        //定位数组        int start[10] = {0};        for(int i = 1 ;i < 10;++i)        {            start[i] = start[i - 1] + counts[i - 1];        }        //往桶里扔        for(int i = 0;i < size;++i)        {            int num = (array[i]/base)%10;            int& pos = start[num];            buckets[pos] = array[i];            ++pos;        }        memcpy(array,buckets,sizeof(int)*size);        base *= 10;        delete[] buckets;    }}

时间复杂度:
基数排序的时间复杂度可以理解为O(d*n),d为序列中最大的位数,适用于n值很大,但是关键字较小的序列。

原创粉丝点击