持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天
计数排序
计数排序也是桶排序的一种实现思路,理解起来比基数排序更容易,更直观
思想
拿到一个数组,我们找到它的最大值与最小值:
[1, 2, 4, 6, 8, 9, 10, 2, 7] 最大值:10,最小值:1
能确定的是,其他元素的范围都在最大值与最小值之间,即每一项 ∈ [1, 10]
现在我们准备一个大桶(数组),在这个大桶内放许多小桶(二维数组),小桶的编号(序号)就在数组的最小值与最大值之间,这里就创建从1-10
bigBucket = [undefined,[],[],[],[],[],[],[],[],[]]
当然,上面是js的定义方式,其他严格的语言可以直接定义从0到最大值的二维数组
小桶定义好了,我们把所有待排序的元素依次遍历,逐个放入对应的小桶内:
bigBucket[1] = 1
bigBucket[2] = 2
bigBucket[3]没有对应的元素,所以保持为空
bigBucket[4] = 4
bigBucket[6] = 6
bigBucket[8] = 8
bigBucket[9] = 9
bigBucket[10] = 10
bigBucket[2] = [2, 2] //注意这里有重复元素,意味着不能将其写死直接赋值,要向后追加新元素
bigBucket[7] = 7
现在所有元素放到了小桶里,如果我们按序遍历小桶,取出的元素一定也是有序的
从bigBucket中从小到大依次取出,重新赋值给arr:
[1, 2, 2, 4, 6, 7, 8, 9, 10]
实现(javascript)
function countingSort(arr){
//初始化大桶
let bigBucket = [];
for(let item of arr){
if(bigBucket[item] === undefined){
bigBucket[item] = [];
}
bigBucket[item].push(item);
}
let pos = 0;
for(let item of bigBucket){
while(item != undefined && item.length != 0){
arr[pos++] = item.shift()
}
}
return arr;
}
时空复杂度及稳定性
时间复杂度仅为O(n)
空间复杂度O(n + k),k为额外用到的数组空间,但我们这里的实现直接原地覆盖掉原数组,个人认为空间复杂度仅为O(k),只额外用到了桶(数组)空间
稳定性:没有发生数据的交换,故稳定