排序算法总结-快速排序

思路

1、找到中间位置 midValue
2、遍历数组,小于 midValue 放左边,大于 midValue 放右边
3、继续递归,最后 concat,返回

获取 midValue 的两种方式:
1、通过 splice,会修改原数组
2、使用 slice,不会修改原数组【推荐】

有二分,时间复杂度就有 O(logn)
其他排序一般都是 O(n^2),快速排序 O(n*logn)相对好一点

代码

/**
 * 快速排序(使用 splice)
 * @param arr number arr
 */
export function quickSort1(arr: number[]): number[] {
    
    
    const length = arr.length
    if (length === 0) return arr

    const midIndex = Math.floor(length / 2)
    const midValue = arr.splice(midIndex, 1)[0]

    const left: number[] = []
    const right: number[] = []

    // 注意:这里不用直接用 length ,而是用 arr.length 。因为 arr 已经被 splice 给修改了
    for (let i = 0; i < arr.length; i++) {
    
    
        const n = arr[i]
        if (n < midValue) {
    
    
            // 小于 midValue ,则放在 left
            left.push(n)
        } else {
    
    
            // 大于 midValue ,则放在 right
            right.push(n)
        }
    }

    return quickSort1(left).concat(
        [midValue],
        quickSort1(right)
    )
}
/**
 * 快速排序(使用 slice)
 * @param arr number arr
 */
export function quickSort2(arr: number[]): number[] {
    
    
    const length = arr.length
    if (length === 0) return arr

    const midIndex = Math.floor(length / 2)
    const midValue = arr.slice(midIndex, midIndex + 1)[0]

    const left: number[] = []
    const right: number[] = []

    for (let i = 0; i < length; i++) {
    
    
        if (i !== midIndex) {
    
    
            const n = arr[i]
            if (n < midValue) {
    
    
                // 小于 midValue ,则放在 left
                left.push(n)
            } else {
    
    
                // 大于 midValue ,则放在 right
                right.push(n)
            }
        }
    }

    return quickSort2(left).concat(
        [midValue],
        quickSort2(right)
    )
}
// 功能测试
const arr1 = [1, 6, 2, 7, 3, 8, 4, 9, 5]
console.info(quickSort2(arr1))

splice 和 slice 性能比较

// 性能测试
const arr1 = []
for (let i = 0; i < 10 * 10000; i++) {
    
    
    arr1.push(Math.floor(Math.random() * 1000))
}
console.time('quickSort1')
quickSort1(arr1)
console.timeEnd('quickSort1') // 74ms

const arr2 = []
for (let i = 0; i < 10 * 10000; i++) {
    
    
    arr2.push(Math.floor(Math.random() * 1000))
}
console.time('quickSort2')
quickSort2(arr2)
console.timeEnd('quickSort2') // 82ms

发现时间相差无几,分析原因:
1、算法本身的复杂度已经够高了 O(n*logn)
2、splice 是逐步二分后执行的,二分会快速削减数量级

接下来我们单独比较splice 和 slice

// 单独比较 splice 和 slice
const arr1 = []
for (let i = 0; i < 10 * 10000; i++) {
    
    
    arr1.push(Math.floor(Math.random() * 1000))
}
console.time('splice')
arr1.splice(5 * 10000, 1)
console.timeEnd('splice')  // 0.08ms
const arr2 = []
for (let i = 0; i < 10 * 10000; i++) {
    
    
    arr2.push(Math.floor(Math.random() * 1000))
}
console.time('slice')
arr2.slice(5 * 10000, 5 * 10000 + 1)
console.timeEnd('slice') // 0.007ms

slice 大概要比 splice 快十倍,但还是都很快的。

猜你喜欢

转载自blog.csdn.net/weixin_43972437/article/details/130375130