Summary of sorting algorithms - quick sort

train of thought

1. Find the middle position midValue
2. Traverse the array, put it on the left if it is less than midValue, and put it on the right if it is greater than midValue
3. Continue recursion, finally concat, and return

There are two ways to get midValue:
1. Through splice, the original array will be modified.
2. Using slice will not modify the original array [Recommended]

With two points, the time complexity is O(logn).
Other sorts are generally O(n^2), and quick sort O(n*logn) is relatively better.

the code

/**
 * 快速排序(使用 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 and slice performance comparison

// 性能测试
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

The time difference is found to be almost the same, and the reasons are analyzed:
1. The complexity of the algorithm itself is already high enough to be O(n*logn)
2. The splice is executed after the gradual dichotomy, and the dichotomy will quickly reduce the order of magnitude

Next we compare splice and slice separately

// 单独比较 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 is about ten times faster than splice, but still fast.

Guess you like

Origin blog.csdn.net/weixin_43972437/article/details/130375130