【算法】计数排序以及其java实现

前几周算法课看算法导论看到一个排序叫计数排序,据说是一个很骚的东西,其时间复杂度为O(n)。要知道很骚的快速排序其平均时间复杂度也是O(nlgn)。看完了算法的推导过程才发现,原来只是一个空间换时间的策略。

首先,它需要我们准备三个数组,需要排序的数组A,排序后的数组B,二者同样大小。然后中间数组C,C的大小为A中最大值+1.(这个就很坑,比如我A[2] = {1,9999}那么它就会默认建立的C数组长度为10000。然而用别的排序根本用不到这么大的空间。没办法,谁让其的策略就是空间换时间呢) 然后C数组的下标代表A数组中的值,C数组对应下标的值代表下标值在A数组中出现的次数。如下图所示例子:

别看这里的C长度为4,万一A中有0呢?)

然后对C中的每个值变化为其之前所有值与本身值之和,表示A中小于等于自己的一共有多少个数。


然后,从末尾遍历A数组,找寻A数组对应的值作为下标在C数组中对应的值。然后该值就是A数组中值在B数组中值的位置:


B数组更新完后,C数组对应的位置值-1.代表剩下的A数组中小于等于该值的个数。

依次遍历一遍,就将A数组中所有的值放到了B数组中对应的位置中。

总的说来,虽然其看起来时间复杂度是O(n),但是其背后的代价是蛮大的。所以只在巨大样本的排序中会比其他排序快。并且尽量控制A数组中最大值和A数组长度的比例,不然弄一个巨长的数组C但是其变化寥寥,就比较浪费空间了。

下面是java实现的源代码。由于经常刷leetcode,得了一种不把多余的全部删掉就会死的病。所以没有注释,代码也比较紧凑,见谅。

    

public int[] JishuSort(int a[])
	{
		int cnum =0;
		for(int i = 0 ; i<a.length;i++){
			if(cnum<a[i])
				cnum = a[i];
		}			
		int[] c = new int[cnum+1];
		int[] b = new int[a.length];
		for(int i =0;i<c.length;i++)
			c[i]=0;
		for(int i = 0;i<a.length;i++)
			c[a[i]]+=1;
		for(int i =1;i<c.length;i++)
			c[i]+=c[i-1];
		for(int i = a.length-1;i>=0;i--){
			b[c[a[i]]-1]=a[i];
			c[a[i]]-=1;
		}
		return b;
	}


猜你喜欢

转载自blog.csdn.net/qq_31548387/article/details/78846706