全栈工程师开发手册 (作者:栾鹏)
js系列教程5-数据结构和算法全解
一看到这个名字就会觉得奇特,几个意思,我排序还要再准备几个桶不成?还真别说,想用桶排序还得真准备几个桶,但是此桶非彼桶,这个桶是用来装数据用的。其实桶排序和计数排序还有点类似,计数排序是找一个空数组把值作为下标找到其位置,再把出现的次数给存起来,这似乎看似很完美,但也有局限性,不用小编说相信读者也能明白,既然计数是把原数组的值当做下标来看待,那么该值必然是整数,那假如出现小数怎么办?这时候就出现了一种通用版的计数排序——桶排序。
小编觉得桶排序可以这么理解,它是以步长为分隔,将最相近数据分隔在一起,然后再在一个桶里排序。好了,现在有个概念,步长是什么玩意?这么来说吧,比如在知道十位的情况下48和36有比较的必要吗?显然没有,十位就把你干下去了,还比什么?那在这里可以简单的把步长理解为10,桶排序就是这样,先把同一级别的分到一组,由同一级别的元素进行排序。
代码实现:
@param array 数组
@param num 桶的数量
function bucketSort(array, num) {
if (array.length <= 1) {
return array;
}
var len = array.length, buckets = [], result = [], min = max = array[0], space, n = 0;
var index = Math.floor(len / num) ;
while(index<2){
num--;
index = Math.floor(len / num) ;
}
console.time('桶排序耗时');
for (var i = 1; i < len; i++) {
min = min <= array[i] ? min : array[i];
max = max >= array[i] ? max : array[i];
}
space = (max - min + 1) / num; //步长
for (var j = 0; j < len; j++) {
var index = Math.floor((array[j] - min) / space);
if (buckets[index]) { // 非空桶,插入排序
var k = buckets[index].length - 1;
while (k >= 0 && buckets[index][k] > array[j]) {
buckets[index][k + 1] = buckets[index][k];
k--;
}
buckets[index][k + 1] = array[j];
} else { //空桶,初始化
buckets[index] = [];
buckets[index].push(array[j]);
}
}
while (n < num) {
result = result.concat(buckets[n]);
n++;
}
console.timeEnd('桶排序耗时');
return result;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(bucketSort(arr,4));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50];
但是这边有个坑点,就是桶的数量不能过多,也就说说至少两个桶!为什么?你试下就知道了!
附图理解: