[Alg]排序算法之计数排序

本文详细介绍了两种排序算法:计数排序和分布统计排序。计数排序通过统计序列中小于某项的元素数量来确定排序位置,而分布统计排序则统计关键词的重复次数,再将其转化为位置信息进行排序。文章提供了C语言实现的源代码,并讨论了如何在有限空间内进行原位排序。
摘要由CSDN通过智能技术生成

排序算法之计数排序

作者:屎壳郎 miaosg01@163.com

日期:July 2021

版次:初版

简介: 根据数据结构和排序目的不同,排序过程的处理手法也各异。有的场合只需知道数据的位置信息,那我们可以采用计数排序,用一个辅助表统计各项的位置信息,而不用移动数据。有时数据结构较大,移动数据的开销很大,这就很适合链接排序,加入一个地址链接,通过改变链接来排列数据,从而避免大量数据的移动。本文重点介绍了采用辅助表统计的计数排序和分布统计排序。

1.计数排序

  计数排序的基本思想很朴素,其原理是统计序列中比某项小(或大)的项的数量,从而确定该项在排序时(升序或降序)应该放置的位置。例:序列 ( R 1 , R 2 , R 3 , R 4 , R 5 ) (R_1,R_2,R_3,R_4,R_5) (R1,R2,R3,R4,R5),其值为 ( 1 , 3 , 5 , 4 , 2 ) (1,3,5,4,2) (1,3,5,4,2)。如何确定 R 2 ( = 3 ) R_2(=3) R2(=3)的位置呢?我们把 R 2 ( = 3 ) R_2(=3) R2(=3) R R R中其它项逐一比较,统计出比 R 2 ( = 3 ) R_2(=3) R2(=3)小的项 ( R 1 ( = 1 ) , R 5 ( = 2 ) ) (R_1(=1), R_5(=2)) (R1(=1),R5(=2))共两项,故在升序排序中 R 2 ( = 3 ) R_2(=3) R2(=3)应该排在 R 1 , R 5 R_1, R_5 R1,R5之后,居第三的位置。

  该算法需要一个与 R R R相同容量辅助表 C O U N T COUNT COUNT来记录统计结果,还以上面 R R R为例,首先以 R 5 R_5 R5为基准,与 R 4 , R 3 , R 2 R 1 R_4, R_3,R_2 R_1 R4,R3,R2R1逐一比较,如果 R 5 > R j ( j = 4 , 3 , 2 , 1 ) R_5>R_j(j=4,3,2,1) R5>Rj(j=4,3,2,1),则 C O U N T [ 5 ] = C O U N T [ 5 ] + 1 COUNT[5]=COUNT[5]+1 COUNT[5]=COUNT[5]+1;否则 C O U N T [ j ] = C O U N T [ j ] + 1 COUNT[j]=COUNT[j]+1 COUNT[j]=COUNT[j]+1。依次取 R 4 , R 3 , R 2 R_4,R_3,R_2 R4,R3,R2为基准,与它前面的项进行比较,最终得到 C O U N T COUNT COUNT表,其值加一即为对应项排序后的位置。

算法C:(计数排序算法)

  • C1 [COUNT清零] C O U N T [ 1 ] COUNT[1] COUNT[1] C O U N T [ N ] COUNT[N] COUNT[N]都设为零;
  • C2 [执行外循环] i = N , N − 1 , … , 2 i = N, N-1,\ldots, 2 i=N,N1,,2,然后结束;
  • C3 [执行内循环] j = i − 1 , i − 2 , … , 1 j = i-1, i-2, \ldots, 1 j=i1,i2,,1,执行C4;
  • C4 [比较] 如果 R [ i ] < R [ j ] R[i]<R[j] R[i]<R[j] C O U N T [ j ] COUNT[j] COUNT[j]加1;否则, C O U N T [ i ] COUNT[i] COUNT[i]加1.

点评: 该算法对不同的数进行比较,且每次比较都进行一次记账操作,故其比较记账操作都为 N ( N − 1 ) / 2 N(N-1)/2 N(N1)/2次,时间复杂度 O ( N 2 ) O(N^2) O(N2),因其需要两两比较,原理上无法摆脱对 N 2 N^2 N2的依赖,但在细节上还可以进一步优化。如下:

算法C改进:合并条件分支

在算法C4中,有一个在内循环中的if-else条件分支结构,如何合并条件分支以提高程序运行速度? 可以按如下思路进行,假设if的执行条件为 A A A,则else执行条件 A ‾ \overline{A} A,我们可以把else中执行相反操作合并入if分支中。以代码来展示说明具体操作:

for(int i = N; i > 0; i++){
	for(int j = i - 1; j >= 0; j++){
		if(K[i] < K[j]){ 
			COUNT[j] += 1;
			}
		else{
			COUNT[i] +=1;
		}
	}
}

合并条件分支后的代码:

for(int i = N; i > 0; i++){
	COUNT[i] = i;
	for(int j = i - 1; j >= 0; j++){
		if(K[i] < K[j]){
			COUNT[i] -= 1;
			COUNT[j] += 1;
			}
	}
}

C O U N T [ i ] =

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值