整體步驟:
① 選取待排序數(shù)組中其中一個(gè)數(shù)作為基數(shù)(建議選取第一個(gè)數(shù))颅围,使flag等于基數(shù)的下標(biāo),left等于待排序數(shù)組第一個(gè)數(shù)的下標(biāo)裹芝,right等于待排序數(shù)組最后一個(gè)數(shù)的下標(biāo)部逮。
② 將數(shù)組中比基數(shù)小的數(shù)放到它的左邊,比基數(shù)大的數(shù)放到它的右邊嫂易。
③ 將基數(shù)左邊的數(shù)組作為待排序數(shù)組兄朋,重復(fù)①步驟。
④ 將基數(shù)右邊的數(shù)組作為待排序數(shù)組炬搭,重復(fù)①步驟蜈漓。
⑤ 直到left >= right,代表數(shù)組已經(jīng)劃分為最小單位(待排序數(shù)組長度小于等于1)宫盔,即該部分排序完畢融虽,無需繼續(xù)分割數(shù)組。
/**
* 快速排序
* @param num 待排序數(shù)組
*/
function quickSort(num) {
_quickSort(num, 0, num.length - 1); // 將整個(gè)num數(shù)組快速排序灼芭,left和right分別指向數(shù)組左右兩端有额。
}
/**
* 快速排序(遞歸)
* @param num 待排序數(shù)組
* @param left 左指針
* @param right 右指針
*/
function _quickSort(num, left, right) {
if (left >= right) return; // 若左右指針相遇,待排序數(shù)組長度小宇1,即遞歸的終點(diǎn)巍佑,return(注意不能寫成left==right茴迁,這里left是有可能大于right的)。
var i = left, j = right, flag = left; // 定義可移動(dòng)的左右指針 i萤衰,j堕义,定義flag為基數(shù)下標(biāo)。
while (i < j) { // 在i<j時(shí)不斷循環(huán)脆栋,i一旦與j碰頭倦卖,則跳出循環(huán)。
while (num[j] >= num[flag] && j > flag) j--; // j不斷左移椿争,找到在num[flag]右側(cè)且比它大的數(shù)怕膛。
if (i >= j) {
break; // 由于j可能已被改變,需再次判斷i與j是否碰頭秦踪。
}
while (num[i] <= num[flag] && i < j) i++; // i不斷右移褐捻,找到且比基數(shù)小的數(shù),且i不能與j碰頭椅邓。(由于兩次交換已合并柠逞,此處不需要使得i在flag左側(cè))
// num[flag] num[j] num[i]三者換位,可用ES6語法糖[num[flag],num[j],num[i]] = [num[j],num[i],num[flag]];
let temp = num[flag];
num[flag] = num[j];
num[j] = num[i];
num[i] = temp
flag = i; // 基數(shù)已經(jīng)在原num[i]的位置希坚,flag同時(shí)也要賦值成i边苹。
}
_quickSort(num, left, flag - 1); // 將flag左邊數(shù)組作為待排序數(shù)組,遞歸調(diào)用裁僧。
_quickSort(num, flag + 1, right); // 將flag右邊數(shù)組作為待排序數(shù)組个束,遞歸調(diào)用。
}