桶排序顾名思义,桶是装东西的
这里是把需要排序的东西,根据某种映射关系和桶关联起来,再放进去
那么桶的选择就非常重要,比如有一个很多大数的数组,我们要用桶排序
需要建立若干个桶形成映射,当然这不太合适,所以这种场景下就不要使用桶排序了
简单举个例子,就能理解桶排序了
假设有个待排序数组:[100,101,045,021]
其中个位最大的是是5,建立一个下标能到5的桶
[[],[],[],[],[],[]]
1.根据个位[[100],[101, 21],[],[],[],[45]]
2.从左到右倒出来[100,101,21,45],此时个位上有序
看十位建桶
3.根据十位[[100,101],[],[21],[],[45]]
4.从左到右倒出来[100,101,21,45], 此时个位十位上有序
5.根据百位[[21,45],[100,101]]
6.从左到右倒出来[21,45,100,101] ,此时数组有序
为什么都是从右到左倒出来
因为是升序的数组
每一次排序会让数组在某个位上有序
比如第一次让个位有序了,不能让十位倒出来的时候从右往左
要么一直从右往左,降序
要么从左往右,升序
基数排序
基数排序的思想是将整数按位数切割成不同的数字,
然后按每个位数分别比较从而得到有序的序列。
是不是和上面的桶排序很像,因为基数排序是桶排序的扩展
function radixSort(arr) {
if (arr===null || arr.length<2) {
return
}
radixSortMain(arr, 0, arr.length-1, maxBitsLen(arr))
}
function maxBitsLen(arr) {
let max = Number.MAX_VALUE
arr.forEach(element => {
max = Math.max(max, element)
});
let len = 0
while (max > 0) {
len++
max /= 10
}
return len
}
function getDigit(num, index) {
return (num/Math.pow(10, index)%10)>>0
}
function radixSortMain(arr, L, R, len) {
const radix = 10
let i = 0
let j = 0
const bucket = []
for (let t = 0; t < len; t++) {
const count = Array(10).fill(0)
for(i = L; i<=R ; i++) {
j = getDigit(arr[i], t)
count[j]++
}
for(i = 1;i<radix;i++) {
count[i] = count[i] + count[i-1]
}
for(i=R;i>=L;i--) {
j=getDigit(arr[i], t)
bucket[count[j]-1] = arr[i]
count[j]--
}
for(i=L,j=0;i<=R;i++,j++) {
arr[i] = bucket[j]
}
}
}
let arr = [9,8,5,4,2,1,3,3]
radixSort(arr)
console.log(arr)