• 计数排序


      前面提到的排序(选择排序、插入排序、归并排序、快速排序、堆排序等)都是比较排序。也就是说,以上排序实现的思路都是需要元素的比较才能实现。换一种思路,是不是元素排序必须需要数组内的元素之间的比较呢?其实不然,今天介绍的计数排序就不是利用比较,而是巧妙的利用了下标和元素的关系进行排序,把时间转换成空间,典型的时空变换思路。

      在这个思想中,需要维护三个数组a[],b[],c[],数组a是原始的输入数组,数组b是排序后需要输出的数组,数组c是计数数组。这就是所需要的空间。

      首先,初始化计数数组c。那么到底我们需要维护一个多大的计数数组呢?这就要求我们必须知道原始输入数组中的最大值。开辟一个大小为原始输入的最大值的数组,并且c中每个元素都初始化为0。为什么要这么做呢。因为数组c的下标即为原始值,每个下标所对应的数值即为此数值的个数。例如c[5] = 10,就表示a中有10个5。

      其次,就是对数组c中的数值进行修改。即c[a[i]]++。循环a中的所有元素,把每个c[a[i]]自增1。这个不难理解。就是统计每个元素的个数。

      然后就是关键的第一步,c[i] = c[i] + c[i-1]。这句代码的意思就是,比原始值i小的数值个数是c[i]+ c[i-1]。这个开始有点绕,不妨这样想一下:c中第i个数就是原始i的个数,前面所有的(0到i-1)都是比i小的数,把他们都加起来就是所有比i小的数值的个数。这句话就是完成这么一个功能。为什么要实现这么一个功能呢?接下来就是关键的第二步,排序。

      最后这一步排序其实已经很明白了。我已经知道比我小的数的个数了,那我就应该直接放在那些个数的后面一个不就完了?确实是这样。也就是b[c[a[i]] - 1] = a[i](考虑到了数组下标为0所以减1)。正因为如此,简化了时间复杂度。这样其实还没有完,还有一个十分重要的步骤,那就是把所对应的c中的数值(计数个数)减一,因为你已经把一个 i 放进b里面了。

      具体C++代码如下,已经在CB完美运行。

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int c[100];
     5 void countingSort(int a[], int b[], int max, int len) {
     6     for(int i = 0; i <= max; ++i){
     7         c[i] = 0;
     8     }
     9 
    10     for(int i = 0; i != len; ++i){
    11         c[a[i]] = c[a[i]] + 1;
    12     }
    13 
    14     for(int i = 1; i <= max; ++i){
    15         c[i] = c[i] + c[i - 1];
    16         cout<<c[i]<<endl;
    17     }
    18 
    19     for(int i = len-1; i >= 0; --i){
    20         b[c[a[i]] - 1] = a[i];
    21         c[a[i]] = c[a[i]] - 1;
    22     }
    23 }
    24 
    25 int main() {
    26     int a[8] = {2,5,3,0,2,3,0,3};
    27     int b[8];
    28     int max = 5;
    29     int len = sizeof(a)/sizeof(int);
    30     countingSort(a, b, max, len);
    31 
    32     for(int i = 0; i < 8; ++i)
    33         cout<<b[i]<<" ";
    34 
    35     return 0;
    36 }
  • 相关阅读:
    go基础_定时器
    作业3:写一个测试程序,消耗固定内存
    Hdu3397Sequence operation线段树
    Hdu3308LCIS线段树
    Poj3667Hotel线段树
    Poj1436Horizontally Visible Segments线段树
    Poj3225Help with Intervals区间线段树
    Poj2528Mayor's posters线段树
    poj3468A Simple Problem with Integers区间和线段树
    Hdu1698Just a Hook线段树区间更新
  • 原文地址:https://www.cnblogs.com/zhaoyansheng/p/5166111.html
Copyright © 2020-2023  润新知