问题描述:
快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。
步骤:
1. 从数列中挑出一个元素,称为 "基准"(pivot);
2. 重新排序数组,所有的元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序
/**
* quick sort
* @param {Array} arr
* @param {number} left
* @param {number} right
* @return {Array}
*/
function quickSort(arr, left, right) {
var len = arr.length,
partitionIndex,
left = typeof left != 'number' ? 0 : left,
right = typeof right != 'number' ? len - 1 : right;
if (left < right) {
partitionIndex = partition(arr, left, right);
quickSort(arr, left, partitionIndex - 1);
quickSort(arr, partitionIndex + 1, right);
}
return arr;
}
/**
* partition 分区操作
* @param {Array} arr
* @param {number} left
* @param {number} right
* @return {Array}
*/
function partition(arr, left, right) {
var pivot = left, // 设定基准值(pivot)
index = pivot + 1;
for (var i = index; i <= right; i++) {
if (arr[i] < arr[pivot]) {
swap(arr, i, index);
index++;
}
}
swap(arr, pivot, index - 1);
return index - 1;
}
/**
* swap
* @param {Array} arr
* @param {number} i
* @param {number} j
* @return {Array}
*/
function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
/**
* partition
* @param {Array} arr
* @param {number} low
* @param {number} high
* @return {Array}
*/
function partition2(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;
}
/**
* quick sort
* @param {Array} arr
* @param {number} left
* @param {number} right
* @return {Array}
*/
function quickSort2(arr, low, high) {
if (low < high) {
let pivot = partition2(arr, low, high);
quickSort2(arr, low, pivot - 1);
quickSort2(arr, pivot + 1, high);
}
return arr;
}
console.log(quickSort([1, 22, 13, 34, 15], 0));
console.log(quickSort2([1, 22, 13, 34, 15], 0, 4));