基数排序-八大排序汇总(8)

基数排序的性能

排序类别 排序方法 时间复杂度 空间复杂度 稳定性 复杂性
平均情况 最坏情况 最好情况
基数排序 基数排序 O(d(n+r)) O(d(n+r)) O(d(n+r)) O(n+r) 稳定 较复杂

时间复杂度:假设在基数排序中,r为基数,d为位数。则基数排序的时间复杂度为O(d(n+r))。可以看出,基数排序的效率和初始序列是否有序没有关联。

空间复杂度:基数排序过程中,对于任何位数上的基数进行“装桶”操作时,都需要n+r个临时空间。

算法稳定性:基数排序过程中,每次都是将当前位数上相同数值的元素统一“装桶”,并不需要交换位置。所以基数排序是稳定的算法。

代码及分析

以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相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中。
 
代码:
  1 #include "stdafx.h"
  2 #include <iostream>
  3 #include <math.h>
  4 using namespace std;
  5 
  6 //查询数组中的最大数
  7 int findMaxNum(int *p, int n)
  8 {
  9     int i;
 10     int max = 0;
 11     for (i = 0; i < n; i++)
 12     {
 13         if (*(p + i) > max)
 14         {
 15             max = *(p + i);
 16         }
 17     }
 18     return max;
 19 }
 20 //获取数字的位数
 21 int getLoopTimes(int num)
 22 {
 23     int count = 1;
 24     int temp = num / 10;
 25     while (temp != 0)
 26     {
 27         count++;
 28         temp = temp / 10;
 29     }
 30     return count;
 31 }
 32 
 33 //将数字分配到各自的桶中,然后按照桶的顺序输出排序结果
 34 void sort2(int *p, int n, int loop)
 35 {
 36     //建立一组桶此处的20是预设的根据实际数情况修改
 37     int buckets[10][20] = {};
 38     //求桶的index的除数
 39     //如798个位桶index=(798/1)%10=8
 40     //十位桶index=(798/10)%10=9
 41     //百位桶index=(798/100)%10=7
 42     //tempNum为上式中的1、10、100
 43     int tempNum = (int)pow(10, loop - 1);
 44     int i, j;
 45     for (i = 0; i < n; i++)
 46     {
 47         int row_index = (*(p + i) / tempNum) % 10;
 48         for (j = 0; j < 20; j++)
 49         {
 50             if (buckets[row_index][j] == NULL)
 51             {
 52                 buckets[row_index][j] = *(p + i);
 53                 break;
 54             }
 55         }
 56     }
 57     //将桶中的数,倒回到原有数组中
 58     int k = 0;
 59     for (i = 0; i < 10; i++)
 60     {
 61         for (j = 0; j < 20; j++)
 62         {
 63             if (buckets[i][j] != NULL)
 64             {
 65                 *(p + k) = buckets[i][j];
 66                 buckets[i][j] = NULL;
 67                 k++;
 68             }
 69         }
 70     }
 71 }
 72 
 73 //基数排序
 74 void bucketSort3(int *p, int n)
 75 {
 76     //获取数组中的最大数
 77     int maxNum = findMaxNum(p, n);
 78     //获取最大数的位数,次数也是再分配的次数。
 79     int loopTimes = getLoopTimes(maxNum);
 80     int i;
 81     //对每一位进行桶分配
 82     for (i = 1; i <= loopTimes; i++)
 83     {
 84         sort2(p, n, i);
 85     }
 86 }
 87 void testBS()
 88 {
 89     int a[] = { 2, 343, 342, 1, 123, 43, 4343, 433, 687, 654, 3 };
 90     int *a_p = a;
 91     //计算数组长度
 92     int size = sizeof(a) / sizeof(int);
 93     //基数排序
 94     bucketSort3(a_p, size);
 95     //打印排序后结果
 96     int i;
 97     for (i = 0; i < size; i++)
 98     {
 99         printf("%d\n", a[i]);
100     }
101 }
102 
103 int _tmain(int argc, _TCHAR* argv[])
104 {
105     testBS();
106 
107     system("pause");
108     return 0;
109 }

关于基数排序性能优化一篇非常牛的文章

http://blog.csdn.net/yutianzuijin/article/details/22876017

posted on 2015-10-04 21:11  306573704  阅读(811)  评论(0编辑  收藏  举报

导航