算法学习记录(六)

108 阅读1分钟

非比较排序

问:

  1. 计数排序
  2. 基数排序

解:

  1. 计数排序(与数据状况有关,范围太大不合适)
    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)