• 基数排序-八大排序汇总(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
    ", 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

  • 相关阅读:
    php实现一个简单的四则运算计算器
    linux下service+命令和直接去执行命令的区别,怎么自己建立一个service启动
    mongodb
    随笔一个dom节点绑定事件
    php-fpm 启动参数及重要配置详解
    PHP的设计模式之工厂模式
    linux下mysql数据的导出和导入
    windows下mongodb安装与使用图文教程(整理)
    MySQL性能分析及explain的使用
    nginx反向代理缓存服务器的构建
  • 原文地址:https://www.cnblogs.com/SnailProgramer/p/4855016.html
Copyright © 2020-2023  润新知