计数排序(Counting Sort)
标签
稳定排序、非原地排序、非比较排序
基本思想
计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出,它的优势在于对较小范围内的整数排序。它的复杂度为$Ο(n + k)$(其中$k$是待排序数的范围),快于任何比较排序算法,缺点就是非常消耗空间。很明显,如果而且当$O(k) > O(nlog n)$的时候其效率反而不如基于比较的排序,比如堆排序、归并排序和快速排序。
计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。 作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。对于给定的输入序列中的每一个元素$x$,确定该序列中值小于$x$的元素的个数。一旦有了这个信息,就可以将$x$直接存放到最终的输出序列的正确位置上。例如,如果输入序列中只有17个元素的值小于$x$的值,则$x$可以直接存放在输出序列的第18个位置上。当然,如果有多个元素具有相同的值时,我们不能将这些元素放在输出序列的同一个位置上,在代码中作适当的修改即可。
算法描述
- 步骤1:找出待排序的数组中最大和最小的元素;
- 步骤2:统计数组中每个值为$i$的元素出现的次数,存入数组C的第$i$项;
- 步骤3:对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
- 步骤4:反向填充目标数组:将每个元素$i$放在新数组的第C(i)项,每放一个元素就将C(i)减去1。
动图演示
时间复杂度
当输入的元素是$n$个$0$到$k$之间的整数时,它的运行时间是$O(n + k)$。计数排序不是比较排序,排序的速度快于任何比较排序算法。由于用来计数的数组$C$的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要大量时间和内存。
最佳情况:$O(n + k)$
最差情况:$O(n + k)$
平均情况:$O(n + k)$
空间复杂度
$O(k)$。
$使用一个额外的数组$C$,其中第$i$个元素是待排序数组$A$中值等于$i$的元素的个数。然后根据数组$C$来将A中的元素排到正确的位置。要求待排序数中最大数值不能太大。
计数排序是典型的以空间换时间的排序算法,对待排序的数据有严格的要求,比如待排序的数值中包含负数,最大值都有限制,请谨慎使用。
算法示例
参考资料:
https://blog.csdn.net/coolwriter/article/details/78732728
https://blog.csdn.net/weixin_41190227/article/details/86600821
https://www.cnblogs.com/itsharehome/p/11058010.html