计数排序
来源:互联网 发布:银行程序员招聘要求 编辑:程序博客网 时间:2024/05/29 18:34
基本原理
计数排序的基本思想就是:加入输入一个数x,如果我们可以找到比x小的数有几个,那么就可以直接将x放入到对应的输出数组的位置。
比如输入一个数x=12,发现在输入的数据中,比12小的有4个,那么毫无疑问12就该排在第五位。
通过上述的描述,可能你会发现,诶那每次我要找到有几个数比12小,不都是要把数组遍历一遍吗?n个数的话就会需要O(n^2),不是慢到怀疑人生吗?
现在就来说一下怎么进行计数排序,首先需要三个数组:
输入数组A,输出数组B(就是保存将A进行排序后的数组),提供中间存储的数组C
现在假设输入数组A={2,5,3,0,2,3,0,3},其中最大的数为5,则令k=5;
那么数组C的大小就为K+1,全部初始化为0;
for i=0 to A.lengthC[A[i]]+=1;
上面这步的目的是统计在A的中每个数出现了几次,然后将这个数作为C数组的下标,出现的次数作为对应下标里面的值。
经过上面这步,C={2,0,2,3,0,1}
还记得在之前说的吗,计数排序是基于“计数排序的基本思想就是:加入输入一个数x,如果我们可以找到比x小的数有几个,那么就可以直接将x放入到对应的输出数组的位置。”,接下来这步就是来统计有几个数比X小。
for j=1;j<C.length;j++C[j]=C[j]+C[j-1]
经过这步C={2,2,4,7,7,8}
通过C数组我们就可以知道5应该排在第8位。这里你可能会对C数组产生疑问,别急,接下去看。
现在就是用到B数组的时候了
for j=A.length-1 to 0 C[A[j]]-=1; B[C[A[j]]]=A[j];
B={0,0,2,2,3,3,3,5}
总的来说就是首先通过遍历一遍A数组,统计出A中每个数出现的次数得到C数组,然后通过C数组的C[i]=C[i]+C[i-1],可以知道每个数有几个数比自己小,也就是A中的每个数该排在哪个位置。这里出现重复的数,通过C[A[i]]-=1;自动处理了。
伪代码
来自《算法导论》
时间复杂度
从上面的伪代码看,第一个for循环时间复杂度是O(k),第二个是O(n),第三个是O(k),第四个是O(n),所以总的是O(k+n),特别当n==k的时候,时间复杂度是O(n)。
计数排序不需要比较操作,也不需要交换操作,是一种简单的排序方式,但是这是一种空间换时间的排序方式,类似的空间换时间的排序还有桶排序等。
特别的当O(k)>=O(nlogn)的时候,计数排序就不那么有效了。
java代码实现
public class CountingSort { public static void main(String[] args) { int[] A = {2,5,3,0,2,3,0,3}; int[] B = CountSort(A); for(int i:B) System.out.print(i+" "); } public static int[] CountSort(int[] A){ int[] B = new int[A.length]; int max=A[0], min=A[0]; for(int i:A){ if(i>max) max=i; if(i<min) min=i; } int[] c =new int[max-min+1]; //对C数组的大小进行优化 for(int i:A){ c[A[i]-min]+=1; } for(int j=1;j<c.length;j++) c[j]=c[j]+c[j-1]; for(int j=A.length-1;j>=0;j--){ c[A[j]-min]-=1; B[c[A[j]-min]]=A[j]; } return B; }}
参考资料:
《算法导论》
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- POJ3734_Blocks_快速幂求解递推问题
- HDU5358-First One
- POI复制行支持07,13。同时复制单元格合并
- Ubuntu下通过xrandr和cvt命令修改屏幕分辨率
- 聚合支付-网页版和后台版接口的区别
- 计数排序
- 浅析Swing线程模型和EDT
- MVC和MVVM
- java Json
- JS/jQuery判断数据类型的几种方式
- jar包和war包的介绍和区别
- 软件架构资源汇总
- Julia: 关于下载库时WinRPM的Bug
- 从grub2启动windows