之前的排序都是可以规划为一大类,叫做比较排序,通过数值与数值之间的比较来进行。他们的时间复杂度的下限是o(nlgn),具体的推到可以见算法导论的P98页。下面开始的就不是通过数值之间的比较得到的排序了第一:计数排序。原理是:比如说一个数组中的数值的话,肯定有比这个数值小的数字,那么我们通过记住这么个比该值小的数字的个数,最后一这个个数作为参考,可以直接把数字放到输出数组中,当然,对于一个数组中的某个或者是某几个元素重复的情况也是要考虑进去的,详细情况见下面的代码,当然这代码只是在有限的范围内,有限的数字的排序。PS:昨天看到effective cpp上面 把cpp分为四个有限的语言的联邦: c ,objetc-oriented cpp ,tempalte cpp ,stl。才发现之前的说法是不对的,应该是下次假如重写这个算法的话,要使用objetc-oriented cpp ,tempalte cpp试着写写。哇哈哈
//之前的所有的排序都是比较排序,那么我们可以知道的是有算法导论得到的一个点就是:他们的时间复杂度的下届就是O(nlgn),下面开始都不是使用比较来进行的排序
#include<iostream>
using namespace std;
/*计数排序使用的是三个数组,一个是用于存放输入,一个是输出,一个是用于临时存放,时间复杂度是O(m+n)也就是O(n),因为这里的m是小于n的
*/
#define N 50
void countsort(int *a,int *b,int m,int n)//m>=max(a[])
{
int c[N];//局部定义的一个数组,在函数结束之后本数组会消失;用于暂存数据
for(int i=0;i<=m;++i)
c[i]=0;//对这个暂存的数组用到的部分全部的赋值为0;
for(int j=1;j<=n;++j)
c[a[j]]=c[a[j]]+1;//由于要考虑到的一种情况是a[]中存在有元素重复,那么扫描这个数组,遇到相同元素,对应的在
for(int l=1;l<=m;++l) //c[]中的相应的a[j]为下标的地方加一,到最后的时候得到的是一个c[],下标是a[j],大小是该a[j]出现的次数。这里可以简便的写为:++c[a[j]]
c[l]=c[l]+c[l-1];//这里的一个实际上右边的c[i]和c[i-1]不是在一个数组了(除了i=1 的时候) ,第0开始的话,以后每一个位置上面的数字都不大于这个序列号的数值
for(int p=n;p!=0;--p)
{
b[c[a[p]]]=a[p];//这个步骤是把a[]中的数值按照从从后往前(即从大到小)存放到数组b[]
c[a[p]]=c[a[p]]-1;//这个作用是防止对于a[]中的元素重复的情况。c[a[p]]的意思现在是小于等于a[p]的元素的个数,那么假如把一个重复的元素放到b[]则相应的应该减少1
}
}
int main()
{
int k,n;
int a[N];
int b[N];
cout<<"输入想要的值k:"<<endl;//个人认为这里的k意思就是所有输入序列里面的最大的输入数值,对不对?
cin>>k;
cout<<"输入输入序列的大小n:"<<endl;
cin>>n;
for(int i=1;i<=n;++i)
cin>>a[i];
countsort(a,b,k,n);//计数排序
for(int j=1;j<=n;++j)//排序输出
cout<<b[j]<<endl;
return 0;
}
![](https://img-my.csdn.net/uploads/201207/06/1341558520_9850.png)