基数排序

来源:互联网 发布:java开发管理系统 编辑:程序博客网 时间:2024/05/16 09:47
基数排序
(radix sort)则是属于“分配式排序”(distribution sort),基数排序法又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
1. 工作原理


基数排序的发明可以追溯到1887年赫尔曼·何乐礼在打孔卡片制表机(Tabulation Machine)上的贡献。它是这样实现的:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。
基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。
最高位优先(Most Significant Digit first)法,简称MSD法:先按k1排序分组,同一组中记录,关键码k1相等,再对各组按k2排序分成子组,之后,对后面的关键码继续这样的排序分组,直到按最次位关键码kd对各子组排序后。再将各组连接起来,便得到一个有序序列。
最低位优先(Least Significant Digit first)法,简称LSD法:先从kd开始排序,再对kd-1进行排序,依次重复,直到对k1排序后便得到一个有序序列。
1.1 计算数组中最大位数
1.2 从最后一位(或者第一位)开始将数据分配到桶中
1.3 将桶中数据复制到原数组中
1.4 循环1.2-1.3直到完成


2. 时间复杂度
时间效率:设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集。 空间效率:需要2*radix个指向队列的辅助空间,以及用于静态链表的n个指针。


3. 算法稳定性
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优 先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。


4. 代码实现


int MaxBit(int arr[], int size){int len = 0;int tmp = 1;for (int i = 0; i < size; i++){while (arr[i] >= tmp){len++;tmp *= 10;}}return len;}void sort_redix(int data[], int n)//基数排序{int d = MaxBit(data, n);int *tmp = new int[n];int *count = new int[10];//计数器int j = 0;int k = 0;int radix = 1;for (int 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;//统计每个桶中的记录数count[k]++;}for (j = 1; j < 10; j++)count[j] = count[j - 1] + count[j];//将tmp中的位置依次分配给每个桶for (j = n - 1; j >= 0; j--)//将所有桶中记录依次收集到tmp中{k = (data[j] / radix) % 10;tmp[count[k] - 1] = data[j];count[k]--;}for (j = 0; j < n; j++)//将临时数组的内容复制到data中data[j] = tmp[j];radix *= 10;}delete []tmp;delete []count;}


0 0
原创粉丝点击