学习经典排序算法-JS实现快速排序(quickSort)

8,328 阅读4分钟

这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

在上一篇文章学习了排序方法-桶排序, 另更多更文学习 JavaScript 的系列小总结更多阅读-list & 经典排序算法-list

前面还学了计数排序桶排序, 本文来继续学习经典排序方法: 快速排序 (quickSort), 看其名字就知道是一种相对较快的排序算法:

JS 实现排序算法-快速排序

正如其名快速排序是一种比较快的排序算法.. 就是快, 而且效率高!它是处理大数据最快的排序算法之一了。

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。 快速排序通常明显比其他 Ο(nlogn) 算法更快, 因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。

快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看, 快速排序应该算是在冒泡排序基础上的递归分治法。

快速排序的名字起的是简单粗暴, 虽然 Worst Case 的时间复杂度达到了 O(n²), 但是在大多数情况下都比平均时间复杂度为 O(n logn) 的排序算法表现要更好, 这是为什么呢? 在《算法艺术与信息学竞赛》上的解释:

快速排序的最坏运行情况是 O(n²), 比如说顺序数列的快排。但它的平摊期望时间是 O(nlogn), 且 O(nlogn) 记号中隐含的常数因子很小, 比复杂度稳定等于 O(nlogn) 的归并排序要小很多。所以, 对绝大多数顺序性较弱的随机数列而言, 快速排序总是优于归并排序。

快速排序算法步骤:

  1. 从数列中挑出一个元素, 称为 “基准”(pivot)
  2. 重新排序数列, 所有元素比基准值小的摆放在基准前面, 所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后, 该基准就处于数列的中间位置。这个称为分区(partition)操作;
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

递归的最底部情形, 是数列的大小是零或一, 也就是永远都已经被排序好了。虽然一直递归下去, 但是这个算法总会退出, 因为在每次的迭代(iteration)中, 它至少会把一个元素摆到它最后的位置去。

快速排序 JavaScript代码实现:

function partition(arr, low, high) {
  let pivot = arr[low];
  while (low < high) {
    while (low < high && arr[high] > pivot) {
      --high;
    }
    arr[low] = arr[high];
    while (low < high && arr[low] <= pivot) {
      ++low;
    }
    arr[high] = arr[low];
  }
  arr[low] = pivot;
  return low;
}

function quickSort(arr, low, high) {
  if (low < high) {
    let pivot = partition(arr, low, high);
    quickSort(arr, low, pivot - 1);
    quickSort(arr, pivot + 1, high);
  }
  return arr;
}

测试代码运行耗时的函数

用于创建数组的方法函数:

const testArrFn = function (len) {
  let arr = []
  const count = len
  for (let i = 0; i < count; i++) {
    arr[i] = Math.floor(Math.random() * 50 + 1)
  }
  return arr
}

工具: 通过测试数据(数组), 方法执行的时间

let testArr = testArrFn(len)

let len = testArr.length
/**
 * @desc 方法函数执行的时间
 */
module.exports = async function getFnRunTime(fn) {
  let startTime = Date.now(),
    endTime
  let result = await fn(testArr)
  endTime = Date.now()
  console.log(testArr, result)
  console.log(, "test_array'length: " + len, result.length,`排序耗时-total time: ${endTime - startTime}ms, `)
}
// 引入上面的 统计代码耗时的方法: 进行测试快速排序对处理20000+条数据的排序耗时:
getFnRunTime(quickSort)

更多阅读:

经典排序算法: