基数排序

来源:互联网 发布:软件测试通过的标准 编辑:程序博客网 时间:2024/06/03 04:02

1、基数排序

按组成关键字的各位值进行排序。
以r为基数按LSD排序的实现问题。若关键字是数字,则可以把每个十进位数字作为一个关键字位。关键字为十(二)进制的排序为以10(2)为基数的基数排序。下面以十进制数为例(r=10),介绍基数排序。

2、排序过程

首先按最低位数值(个位)依次把各个元素分配到相应桶中,然后按桶号从小到大和进入桶中数据元素的先后顺序收集在各队列中的数据元素,形成数据元素集合的一个新排列,此为一次基数排序。再对上次得到的序列按次低位(十位)的数值依次把各数据分配到相应队列中,同上,收集元素,得到新序列,.........,重复m次(m位数的基数排序),排序完成。即分配与收集。

示例:

序列:710,342,045,686,6,841,429,134,68,264

一次基数排序(按个位):

分配

0:710

1:841

2:342

3:

4:134   264

5:045  

6:686    006 

7:

8:068

9:429 

收集

710,841,342,134,264,045,686,006,068,429

二次基数排序(按十位):

分配

0:006

1:710    

2:429

3:134   

4:841   342    045 

5:

6:264   068

7:

8:686

9:

收集

006,710,429,134,841,342,045,264,068,686

三次基数排序(按百位):

分配

0: 006   045   068

1: 134

2: 264

3: 342

4: 429

5: 

6: 686  

7: 710

8: 841

9:

收集

006,045,068,134,264,342,429,686,710,841

3、算法分析

对n个记录(每个记录关键字含d位,每位取值范围为r个值),每一趟分配时间复杂度O(n),每一趟收集时间复杂度O(r),整个排序需要d趟收集和分配,时间复杂度量级O(d(n+r)),最好,最坏,平均都是。
空间复杂度:O(n+r)
是稳定的。

代码:

#include <iostream>#include <vector>using namespace std;/** 打印数组*/void printArray(int array[],int length){for (int i = 0; i < length; ++i){cout << array[i] << " ";}cout << endl;}/**求数据的最大位数,决定排序次数*/int maxbit(int data[], int n){    int d = 1; //保存最大的位数    int p = 10;    for(int i = 0; i < n; ++i)    {        while(data[i] >= p)        {            p *= 10;            ++d;        }    }    return d;}void radixsort(int data[], int n) //基数排序{    int d = maxbit(data, n);//获取最大位数    int tmp[n];    int count[10]; //计数器    int i, j, k;    int radix = 1;    for(i = 1; i <= d; i++) //进行d趟排序    {        for(j = 0; j < 10; j++)            count[j] = 0; //每次分配前清空计数器        for(j = 0; j < n; j++)        {//依次按个位、十位、百位......进行排序            k = (data[j] / radix) % 10; //获取个位、十位、百位......是几(0~9)            count[k]++;//统计每个桶中的记录数,个位、十位、百位......是k,则count[k]++        }        for(j = 1; j < 10; j++)            count[j] = count[j - 1] + count[j];            //将tmp中的位置依次分配给每个桶。当前桶j(1~9)以及前面的桶共存数目            //桶j中最后一个进入的数在tmp中下标为count[j]-1        for(j = n - 1; j >= 0; j--) //将所有桶中记录依次收集到tmp中        {            k = (data[j] / radix) % 10;            tmp[count[k] - 1] = data[j];//相当于出队列            count[k]--;//相应桶数目减1        }        for(j = 0; j < n; j++) //将临时数组的内容复制到data中            data[j] = tmp[j];        radix = radix * 10;        cout<<"第"<<i<<"趟收集结果:";        printArray(data,n);    }}int main(){int array[] = {710,342,45,686,6,841,429,134,68,264};int length=sizeof(array)/sizeof(int);cout<<"原数组:"<<endl;printArray(array,length);radixsort(array,length);return 0;}
                                                               


原创粉丝点击