非比较排序
问:
- 计数排序
- 基数排序
解:
- 计数排序(与数据状况有关,范围太大不合适)
function countSort(arr) {
const res = []
const tempArr = []
const otherTempArr = []
arr.forEach(i => {
if (i > 0) {
tempArr[i] ? tempArr[i]++ : tempArr[i] = 1
} else {
otherTempArr[-i] ? otherTempArr[-i]++ : otherTempArr[-i] = 1
}
})
// 正数数组存入
tempArr.forEach((item, idx) => {
// 如果item有值,表明idx代表的值出现过
if (item) {
for (let i =0; i < item; i++) {
res.push(idx)
}
}
})
// 负数数组存入
otherTempArr.forEach((item, idx) => {
if (item) {
for (let i =0; i < item; i++) {
res.unshift(-idx)
}
}
})
return res
}
2.桶排序
const arr = [10,2,400,3000,11,13,14,402]
function bucketSort(arr) {
// 获取最大数的位数
const maxNumber = Math.max(...arr)
const maxDigit = getDigit(maxNumber)
// 辅助数组
const tempArr = []
// 转为字符串、补零
for (let i = 0; i < arr.length; i++) {
const selfDigit = getDigit(arr[i])
arr[i] = '0'.repeat(maxDigit - selfDigit) + arr[i]
}
// 按位数比较,先从个位数开始
for (let i = maxDigit -1; i >= 0; i--) {
// 计算频次数组
const countArr = []
// 计算频次
for (let j = 0; j < arr.length; j++) {
// 每个数的当前位数的值 0011 的第个位、十位、千位
const currentValue = arr[j][i]
// 存值
countArr[currentValue] ? countArr[currentValue]++ : countArr[currentValue] = 1
}
// 此时countArr就是按位数来的频次数组 [3,1,2,1,1]
// 转换成频次累加和数组 [3,4,6,7,8] -> 0有2个 大于等于1的有4个 大于等于2的有6个 大于等于3的有7个 大于等于4的有8个
for (let j = 0; j < countArr.length; j++) {
// 避免NAN
if (!countArr[j]) countArr[j] = 0
if (j !== 0) countArr[j] = countArr[j] + countArr[j - 1]
}
for (let j = arr.length -1; j >= 0; j--) {
// 每个数的当前位数的值 0011 的第个位、十位、千位
const currentValue = arr[j][i]
// 拿到这个表明arr[j]应该放在辅助数组的什么位置 拿到2,大于等于2的有6个,所以放在5位置
tempArr[countArr[currentValue] -1] = arr[j]
// 频次和减一
countArr[currentValue]--
}
// 辅助数组完成了一次根据位数的排序,替换到原数组
arr = JSON.parse(JSON.stringify(tempArr))
}
return arr
}
function getDigit(num) {
let count = 1
while (num / 10 >= 1) {
count++
num /= 10
}
return count
}
bucketSort(arr)