算法导论-排序(四)计数排序(线性时间排序)
目录
1、计数排序介绍
2、流程图
3、代码实现
4、性能分析
5、参考资料
内容
1、计数排序介绍
什么是计数排序?
计数排序是一种特殊的排序算法,之前介绍的排序算法需要对数进行两两比较,效率下界为θ(nlgn); 而计数排序不需要对数进行比较就可以进行排序;很神奇吧,只需要对待排序数组进行遍历就可以排序,效率为Θ(n)。。哈哈,那么神奇,下面开讲!!!!
限制:计数排序只能对非负整数(0,1,2,3...N)进行排序
排序思想:计数排序的基本思想就是对每一个输入元素 x,确定出小于 x 的元素个数。有了这一信息,就可以把 x 直接放到它在最终输出数组中的位置上。例如:有 10 个年龄不同的人,统计出有 8 个人的年龄比 A 小,那 A 的年龄就排在第 9 位,用这个方法可以得到其他每个人的位置,也就排好了序。
2、流程图
排序算法步骤:
1)统计数组中每个值为 X 的元素出现的次数,存入数组 C 的第X 项
2)累加元素出现次数(计算不超过 X包括X 的元素的个数)
3) 将元素X依次放入到适当的位置
排序伪码:
CountSort(A,n,k) //A-待排序数组;n-排序数组元素个数;k-大于等于待排序数组元素最大值的某个整数 步骤一流程图 1)统计数组中每个值为 X 的元素出现的次数,存入数组 C 的第X 项
步骤二 流程图 2)累加元素出现次数(计算不超过 X包括X 的元素的个数)
步骤三流程图 3)将元素X依次放入到适当的位置
3、代码实现(c++)
1 #include <iostream> 2 #include <vector> 3 #include <time.h> 4 using namespace std; 5 6 #define N 10 //排序数组大小 7 #define K 100 //排序数组范围0~K 8 9 void CountSort(vector<int> &A) 10 { 11 //找出待排序数组最大、最小值 12 int min,max; 13 min=max=A[0]; 14 for (int i=1;i<A.size();i++) 15 { 16 if (A[i]<min) min=A[i]; 17 else if (A[i]>max) max=A[i]; 18 } 19 //定义数组B存放排好的数 20 vector<int> B(A.size()); 21 //定义数组C,大小为(max-min+1),C[i]为A中值为i的个数 22 vector<int> C(max-min+1); 23 for (int i=0;i<max-min+1;i++) C[i]=0;//初始为0 24 for(int i=0;i<A.size();i++) C[A[i]-min]++;//计数 25 for (int i=1;i<max-min+1;i++) C[i]+=C[i-1];//累加 26 for (int i=A.size()-1;i>=0;i--) 27 { 28 B[C[A[i]-min]-1]=A[i];//A中值倒序取出放到B中合适位置,并在C计数中减1 29 //因数组下标从0开始,所以减1 30 C[A[i]-min]--; 31 } 32 A.assign(B.begin(),B.end());//B赋给A 33 } 34 ////打印数组 35 void print_element(vector<int> A) 36 { 37 int len=A.size(); 38 for (int i=0;i<len;i++) 39 { 40 std::cout<<A[i]<<" "; 41 } 42 std::cout<<std::endl; 43 } 44 // 随机参数排序数组,产生数组范围0~k的整数 45 void Random(vector<int> &a,int n,int k) 46 { 47 int i=0; 48 srand( (unsigned)time( NULL ) ); 49 while(i<n) 50 { 51 a[i++]=rand()%k; 52 } 53 } 54 55 int main() 56 { 57 vector<int > vec_int(N); 58 Random(vec_int,N,K); 59 cout<<"源数组: "; 60 print_element(vec_int); 61 CountSort(vec_int); 62 cout<<"以排序数组: "; 63 print_element(vec_int); 64 65 system("PAUSE"); 66 return 0; 67 }
4、性能分析
分析性能好的快速排序和本节介绍的计数排序的效率【排序数组取值为0~100的整数,数组大小分别取100,1000,10000,100000测试】
数组大小N | 快速排序(ms) | 计数排序(ms) |
100 | 0.153012 | 0.236982 |
1000 | 6.00759 | 4.61228 |
10000 | 58.4422 | 16.0187 |
100000 | 4176.58 | 169.768 |
分析:当数组元素个数较大时,计数排序效率相当高!
注意:当排序数组元素个数较少时效率会降低,并且数组范围较大时内存消耗会相对增多。
何时使用计数排序:
结: 1)待排序数组为非负整数
2) and 数组范围小,元素个数较多
5、参考资料
【1】http://blog.csdn.net/xyd0512/article/details/8261816
【2】http://www.cnblogs.com/gaochundong/p/sorting_in_linear_time.html
【3】http://www.cnblogs.com/xiao-cheng/archive/2011/10/05/2199657.html