基数排序

基本解法

第一步

以LSD为例,假设原来有一串数值如下所示:

73, 22, 93, 43, 55, 14, 28, 65, 39, 81

首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中:

0

1 81

2 22

3 73 93 43

4 14

5 55 65

6

7

8 28

9 39

第二步

接下来将这些桶子中的数值重新串接起来,成为以下的数列:

81, 22, 73, 93, 43, 14, 55, 65, 28, 39

接着再进行一次分配,这次是根据十位数来分配:

0

1 14

2 22 28

3 39

4 43

5 55

6 65

7 73

8 81

9 93

第三步

接下来将这些桶子中的数值重新串接起来,成为以下的数列:

14, 22, 28, 39, 43, 55, 65, 73, 81, 93

这时候整个数列已经排序完毕;如果排序的对象有三位数以上,则持续进行以上的动作直至最高位数为止。

LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好。MSD的方式与LSD相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中。

实现方法

最高位优先(Most Significant Digit first)法,简称MSD法:先按k1排序分组,同一组中记录,关键码k1相等,再对各组按k2排序分成子组,之后,对后面的关键码继续这样的排序分组,直到按最次位关键码kd对各子组排序后。再将各组连接起来,便得到一个有序序列。

最低位优先(Least Significant Digit first)法,简称LSD法:先从kd开始排序,再对kd-1进行排序,依次重复,直到对k1排序后便得到一个有序序列。

实现原理

基数排序的发明可以追溯到1887年赫尔曼·何乐礼在打孔卡片制表机(Tabulation Machine)上的贡献。它是这样实现的:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。

代码

 1 int maxbit(int data[], int n) //辅助函数,求数据的最大位数
 2 {
 3     int d = 1; //保存最大的位数
 4     int p = 10;
 5     for(int i = 0; i < n; ++i)
 6     {
 7         while(data[i] >= p)
 8         {
 9             p *= 10;
10             ++d;
11         }
12     }
13     return d;
14 }
15 void radixsort(int data[], int n) //基数排序
16 {
17     int d = maxbit(data, n);
18     int *tmp = newint[n];
19     int *count = newint[10]; //计数器
20     int i, j, k;
21     int radix = 1;
22     for(i = 1; i <= d; i++) //进行d次排序
23     {
24         for(j = 0; j < 10; j++)
25             count[j] = 0; //每次分配前清空计数器
26         for(j = 0; j < n; j++)
27         {
28             k = (data[j] / radix) % 10; //统计每个桶中的记录数
29             count[k]++;
30         }
31         for(j = 1; j < 10; j++)
32             count[j] = count[j - 1] + count[j]; //将tmp中的位置依次分配给每个桶
33         for(j = n - 1; j >= 0; j--) //将所有桶中记录依次收集到tmp中
34         {
35             k = (data[j] / radix) % 10;
36             tmp[count[k] - 1] = data[j];
37             count[k]--;
38         }
39         for(j = 0; j < n; j++) //将临时数组的内容复制到data中
40             data[j] = tmp[j];
41         radix = radix * 10;
42     }
43     delete[]tmp;
44     delete[]count;
45 }
时间: 2024-12-24 11:30:38

基数排序的相关文章

基数排序及C语言实现

基数排序的基本思想是对数字的每一位进行排序,先对个位排序,然后十位,百位--,对每一位进行排序时,要求采用稳定排序算法,比如前面讨论过的计数排序.以一个三位整数为例,过程是这样的: 该算法同样能达到线性复杂度.下面是代码.(好吧,我知道写的很菜--) #include <stdio.h> #define NUM 10 //数组元素个数 void counting_sort(int a[],int b[],int c[],int atemp[]); int main() { int i; int

数据结构-基数排序

#include <iostream> using namespace std; void CountSort(int* a,int k,int n){ int s = 1; for(int i=0;i<k;i++){ s *= 10; } int* b = new int[n]; int* c = new int[n]; for(int i=0;i<n;i++){ b[i] = 0; c[i] = 0; } int tmp1 = 0; for(int i=0;i<n;i++

基本排序算法(冒泡排序 选择排序 插入排序 快速排序 归并排序 基数排序 希尔排序)

冒泡排序 public static void bubbleSort(int[] arr){ int lgn = arr.length; for (int i = 0; i < lgn - 1; i++) { for (int j = 0; j < lgn - 1 - i; j++) { if(arr[j] > arr[j + 1]){ int temp = arr[j + 1]; arr[j + 1] = arr[j]; arr[j] = temp; } } } } 选择排序 publ

基数排序与桶排序,计数排序【详解】

桶排序简单入门篇^-^ 在我们生活的这个世界中到处都是被排序过的东东.站队的时候会按照身高排序,考试的名次需要按照分数排序,网上购物的时候会按照价格排序,电子邮箱中的邮件按照时间排序……总之很多东东都需要排序,可以说排序是无处不在.现在我们举个具体的例子来介绍一下排序算法. 首先出场的是我们的主人公小哼,上面这个可爱的娃就是啦.期末考试完了老师要将同学们的分数按照从高到低排序.小哼的班上只有5个同学,这5个同学分别考了5分.3分.5分.2分和8分,哎,考得真是惨不忍睹(满分是10分).接下来将分

基数排序(桶排序) 不同方法

详细解释:算法导论/数据结构书 1.链式基数排序 //n个数,每个数有g个关键字//排序:从最后的关键字开始到最前的关键字//分配+收集//每个关键字分配+收集需要n+n时间,而共有g个关键字,时间复杂度为O(2ng),效率很高.//如果用数组,数据集中在一个区间,则区间的长度很长,另外的区间的内存浪费了.//用链表可以解决这个问题,且数据不需要先后顺序,所以无必要非要用数组 1 #include <stdio.h> 2 #include <stdlib.h> 3 //个数 4 #

重复造轮子系列--计数,基数排序

计数,基数的中文读音都一样,这翻译的人还嫌我们计算机不够乱,真的想吐槽. 不管了,毕竟代码还是不一样的. 1.计数排序(counter sort): 通过一个上限来统计集合里的数值(或者其他非数值类型映射的数值),并累计比小于自己(包括)的数值的统计的个数,从而形成排序的索引(也就是前面有多少个小于我的,我的位置就确定了). 普通计数排序代码:(仍需优化,valuetype默认是整数类型) 1 template<typename _InIt> 2 void counter_sort(_InIt

基数排序LSD_Radix_Sort

裸基数排序 #include <iostream> using namespace std; struct list_ { int v; int next; }a[1005]; void print(list_ a[],int head) { for (int i = head; i != -1; i = a[i].next) { cout << a[i].v <<" "; } cout << endl; } int LSD_radix_

排序算法----基数排序(RadixSort(L))单链表智能版本

转载http://blog.csdn.net/Shayabean_/article/details/44885917博客 先说说基数排序的思想: 基数排序是非比较型的排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较. 将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零.然后,从最低位开始,依次进行一次排序.在每一次排序中,按照当前位把数组元素放到对应 的桶当中,然后把桶0到桶9中的元素按先进先出的方式放回数组中.这样从最低位排序一直到最高位排序完成以后,

排序算法----基数排序(RadixSort(L,max))单链表版本

转载http://blog.csdn.net/Shayabean_/article/details/44885917博客 先说说基数排序的思想: 基数排序是非比较型的排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较. 将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零.然后,从最低位开始,依次进行一次排序.在每一次排序中,按照当前位把数组元素放到对应 的桶当中,然后把桶0到桶9中的元素按先进先出的方式放回数组中.这样从最低位排序一直到最高位排序完成以后,