算法导论学习之计数排序

之前的排序都是可以规划为一大类,叫做比较排序,通过数值与数值之间的比较来进行。他们的时间复杂度的下限是o(nlgn),具体的推到可以见算法导论的P98页。下面开始的就不是通过数值之间的比较得到的排序了第一:计数排序。原理是:比如说一个数组中的数值的话,肯定有比这个数值小的数字,那么我们通过记住这么个比该值小的数字的个数,最后一这个个数作为参考,可以直接把数字放到输出数组中,当然,对于一个数组中的某个或者是某几个元素重复的情况也是要考虑进去的,详细情况见下面的代码,当然这代码只是在有限的范围内,有限的数字的排序。PS:昨天看到effective cpp上面 把cpp分为四个有限的语言的联邦: 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值