认识桶排序
桶排序和上次实现的计数排序一样不是比较比较排序,所以平均时间复杂度比O(n logn )要小点;
桶排序的时间复杂度与怎样对每个桶中的元素进行排序有关,可以采用快排甚至是递归调用桶排序进行排序;
所以最坏时间复杂度为O(n**2),最好时间复杂度接近O(n),这里就不具体探究时间复杂度了,我们主要学习思想;
桶排序的核心思想就是将序列中的元素尽可能均匀分布到有序的桶中,在对桶中元素排序,最后依次把桶中元素放入序列中即可;
在写具体代码之前我们来思考一下,如何尽可能均匀的将元素放置到对应的桶中?
我猜你先想的是用序列的长度也就是length除以桶的容量来拿到合适的桶的数量;
这么做是可以在每个桶里很均匀的放置元素,但是有没有想过,如何给元素找对应的桶呢?
这里我给大家提供两种思路:确定桶数量逻辑 || 确定桶大小逻辑
这两种说法是为了便于我自己记忆编造的哈,不是官方的哦;
第一种确定数量逻辑,就是你在使用桶排序时给它指定桶的数量num;
根据num我们可以得到桶的大小:const bucketsSize = Math.floor((max - min) / num) + 1;
确定每个元素对应的桶: const index = ~~((array[i] - min) / bucketsSize);
~~是向下取整的意思,因为按位取反的过程中会进行Toint32抽象操作,在这个过程中会将浮点数去掉;
第二种是确定大小逻辑,我们指定了桶的大小bucketSize后;
桶的数量为:~~((maxValue - minValue) / bucketSize) + 1;
确定元素对应的桶:~~(array[i] - minValue) / bucketSize);
桶排序实现
步骤:
- 设置一个定量的数组当作空桶子。
- 寻访序列,并且把项目一个一个放到对应的桶子去。
- 对每个不是空的桶子进行排序。
- 从不是空的桶子里把项目再放回原来的序列中。
function bucketSort(array, bucketCount) {
function swap(arr, i, j) {
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 拿到最大最小元素
let max = array[0];
let min = array[0];
for (let i = 0; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
} else if (array[i] > max) {
max = array[i];
}
}
// 确定桶大小
bucketCount = bucketCount || 5;
const bucketSize = ~~((max - min) / bucketCount) + 1;
console.log(bucketSize);
const buckets = [];
// 将每个元素装入对应的桶
for (let i = 0; i < array.length; i++) {
// 1.获取对应的index并初始化
let index = ~~((array[i] - min) / bucketSize);
!buckets[index] && (buckets[index] = []);
// 2.装桶并插入排序
buckets[index].push(array[i]);
let l = buckets[index].length;
while (l > 0) {
buckets[index][l] < buckets[index][l - 1] &&
swap(buckets[index], l, l - 1);
l--;
}
}
console.log(buckets);
// 装入原数组并返回
array = [];
for (let i = 0; i < buckets.length; i++) {
while (buckets[i].length) {
array.push(buckets[i].shift());
}
}
return array;
}
上面实现的就是可以指定桶数量的桶排序,没有指定桶数量,默认为5,当然也可以指定桶的大小,并且桶类排序任君选择,核心逻辑都是一样的,这里就不一一实现了哈,对了,桶内排序如果你是选择快排,得封装进去哦;