经典算法回顾之计数排序【非基于比较的排序】
基于比较的排序算法是不能突破O(NlogN)的,而非基于比较的排序,如计数排序、桶排序和计数排序,则可以突破O(NlogN)的时间下限。但要注意的是,非基于比较的排序算法的使用都是有条件限制的,例如元素的大小限制,而基于比较的排序则没有这种限制(在一定范围内)。对特定场合有着特殊性质的数据,非基于比较的排序算法则能够巧妙解决。
计数排序的优势是对已知范围的数组进行排序,其基本思想就是对每一个输入元素x,确定出小于x的个数,这样就可以直接把x放到它在最终数组中的位置上。
算法思路为:
- 扫描序列A,以A中每个元素的值为索引,将C中对应位置的次数统计加1,即C[i]为A中i出现的次数。
- 将C从头开始累加,使C[i]为A中值不大于i的元素的个数
- 按照统计出的值,输出结果。
算法代码如下:
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 }