算法:用JS实现快速排序,并说明时间复杂度

37 阅读1分钟

固定算法,固定思路

  • 找到中间位置 midValue
  • 遍历数组,小于midValue放在left,否则放在right
  • 继续递归。最后concat拼接,返回

细节

  • 获取midValue的两种方式
  • 使用splice会修改原数组
  • 使用slice 不会修改原数组 -- 更加推荐

splice (修改原数组做法)

function quickSort1(arr: number[]): number[] {
  let length: number = arr.length
  if (length === 0) return arr

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

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

  for (let i = 0; i < arr.length; i++) {
    const n = arr[i]
    if (n < midValue) {
      left.push(n)
    } else {
      right.push(n)
    }
  }

  return quickSort1(left).concat([midValue], quickSort1(right))
}

const arr4 = [1, 6, 2, 7, 3, 8, 4, 9, 5]
console.info(quickSort1(arr4))

slice (不修改原数组做法)

function quickSort2(arr: number[]): number[] {
  let length: number = arr.length
  if (length === 0) return arr

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

  const left: number[] = []
  const right: number[] = []
 // O(n) 
  for (let i = 0; i < length; i++) {
    if (i !== midIndex) { // 细节
      const n = arr[i]
      // O(logn)
      if (n < midValue) {
        left.push(n)
      } else {
        right.push(n)
      }
    }
  }
 // O(n) * O(logn) = O(nlogn)
  return quickSort1(left).concat([midValue], quickSort1(right))
}

const arr4 = [1, 6, 2, 7, 3, 8, 4, 9, 5]
console.info(quickSort2(arr4))

时间复杂度

  • 有遍历 有二分 -- O(n*logn) 或者 O(nlogn)
  • 如果是常规排序,嵌套循环,复杂度是O(n^2)

splice 和 slice的区别

  • 算法复杂度本身就够高O(n*logn)
  • 外加,splice是逐步二分后执行的,二分会快速削减数量级
  • 如果单独比较splice和slice,效果会非常明显(splice较慢)
// 性能测试
const arr1: number[] = []

for (let i = 0; i < 10 * 10000; i++) {
  arr1.push(Math.floor(Math.random() * 1000))
}
console.time('quickSort1 splice')
quickSort1(arr1)
console.timeEnd('quickSort1 splice') // 78ms

console.time('quickSort2 slice')
quickSort2(arr1)
console.timeEnd('quickSort2 slice') // 88ms