排序11:计数排序

       这里再介绍一种排序算法,该方法也是不需要进行元素间的比较,却能实现排序过程的。不过,与基数排序一样,它所处理的序列也有些限制:序列元素必须为非负整数,且大小有上限。

       仍以序列:49、38、65、97、76、13、27、49为例。计数排序的思想在于:首先,求取该序列中最大的元素,显然为97。然后,创建一个下标为0~97的整型数组counts,且该数组的每个元素均初始化为0。接着,处理待排序序列的第1个元素,该元素是49,则令counts中下标为49的元素加1,也即,counts[49]现在由0变为1。以同样的方式顺次处理待排序序列中的所有剩下的元素。注意,最后处理到49时,同样令counts[49]的值加1,则此时的counts[49]的值变为2。显然,最终的counts数组存放了0~97这些数字在待排序序列中的出现次数(没出现过的则为0),且counts的下标恰好能实现按序排列的目的。接下来要做的就是:从下标0开始直到97,遍历counts数组,每遍历到某个下标i时,假如counts[i]为t,则输出t个i。到了最后,刚才所有的输出顺次相连,明显将形成排序后的结果。

       实际上,这种排序算法不适合讨论是否稳定。不过,你可以把它视为稳定排序。代码如下:

int getMax(int list[],int length)
{
	int max=0;
	for(int i=1;i<length;++i)
	{
		if(list[i]>list[max])
			max=i;
	}
	
	return list[max];
}

void countSort(int list[],int length)
{
	int max=getMax(list,length);
	
	int * counts=new int [max+1];
	for(int i=0;i<=max;++i)
		counts[i]=0;
		
	for(int i=0;i<length;++i)
		++counts[list[i]];
		
	int index=0;
	for(int i=0;i<=max;++i)
	{
		for(int j=1;j<=counts[i];++j)
			list[index++]=i;
	}
	
	delete [] counts;
}

       设序列元素个数为n,该序列中所有的元素均为0~max的整数。显然,无论初始序列为何种情形,都得遍历全部元素,并分别在counts相应的下标值上加1,此操作的总次数为n。然后又遍历counts以执行输出动作,该步的总操作次数为max+1+n。再算上初始时,求取待排序序列中最大值所需要的操作次数n,以及初始化counts所花费的操作次数max+1。整个排序过程总操作次数为:n+max+1+n+max+1+n=3n+2max+2。综上,时间复杂度为O(n+max)。从时间复杂度可看出,该排序是时间性能最好的排序,不过却大大牺牲了存储空间上的性能!由于要用到长度为max+1的数组counts作为辅助存储空间,该算法的空间复杂度为O(max)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值