经典算法回顾之计数排序【非基于比较的排序】

  基于比较的排序算法是不能突破O(NlogN)的,而非基于比较的排序,如计数排序、桶排序和计数排序,则可以突破O(NlogN)的时间下限。但要注意的是,非基于比较的排序算法的使用都是有条件限制的,例如元素的大小限制,而基于比较的排序则没有这种限制(在一定范围内)。对特定场合有着特殊性质的数据,非基于比较的排序算法则能够巧妙解决。

  计数排序的优势是对已知范围的数组进行排序,其基本思想就是对每一个输入元素x,确定出小于x的个数,这样就可以直接把x放到它在最终数组中的位置上。

算法思路为:

  1. 扫描序列A,以A中每个元素的值为索引,将C中对应位置的次数统计加1,即C[i]为A中i出现的次数。
  2. 将C从头开始累加,使C[i]为A中值不大于i的元素的个数
  3. 按照统计出的值,输出结果。

算法代码如下:

 1 #include "stdafx.h"
 2 #include <iostream>
 3 using namespace std;
 4 
 5 void CountingSort(int data[], int size, int range)
 6 {//数据范围为[0,range]
 7     if(data == NULL || range <= 0 || size < 0)
 8         return;
 9     int *ordered = new int[size];//存放排序结果<不会初始化!!>
10     int *count = new int[range+1];//临时存储区,存放统计次数
11 
12     int i;
13     for(i=0; i<=range; i++)//注意范围!!
14         count[i] = 0;//因为不会默认初始化为0
15     for(i=0; i<size; i++)
16         count[data[i]]++;//此时,C[i]为data中i的个数
17 //对于形成最后排序数字,两个注释部分的效果是一样的,二选一即可
18 /*法一:
19     int j=0;
20     for(i=0; i<=range; i++)
21     {
22         while(count[i] != 0)
23         {
24             ordered[j++] = i;
25             count[i]--;
26         }
27     }
28  */
29 /*法二:
30     for(i=1; i<=range; i++)
31         count[i] += count[i-1];//此时,C[i]为data中不大于i的个数
32     for(i=size-1; i>=0; i--)
33     {//对data数组,从后向前确定每个数字所在的最终位置;也可以反向进行
34         ordered[count[data[i]]-1] = data[i];//!!注意需要减1,因为数组从0开始
35         count[data[i]]--;
36     }
37  */
38     for(i=0;i<size;++i)
39         cout<< ordered[i] <<" ";
40     cout<<endl;
41 }
42 
43 int  main()
44 {
45     int unsorted[] = {3,6,1,4,5,5,8,4,9,9,10};
46     int length = sizeof(unsorted)/sizeof(int);
47 
48     for(int i=0;i<length;++i)
49        cout<<unsorted[i]<<" ";
50     cout<<endl;
51 
52     CountingSort(unsorted,length,10);
53 
54     for(int i=0;i<length;++i)
55         cout<<unsorted[i]<<" ";
56     cout<<endl;
57 
58     return 0;
59 }

 

原文地址:https://www.cnblogs.com/dreamrun/p/4368796.html