請你在旁邊的白板寫個快速排序演算法
/**
* 快速排序演算法
* @param {number[]} arr - 要排序的陣列
* @param {number} left - 陣列的左邊界索引
* @param {number} right - 陣列的右邊界索引
* @returns {number[]} - 排序後的陣列
*/
function quickSort(arr, left = 0, right = arr.length - 1) {
// 基礎情況:如果左邊界大於等於右邊界,結束遞迴
if (left >= right) {
return arr;
}
// 獲取分割點(pivot)的索引
const pivotIndex = partition(arr, left, right);
// 遞迴排序左半部分
quickSort(arr, left, pivotIndex - 1);
// 遞迴排序右半部分
quickSort(arr, pivotIndex + 1, right);
return arr;
}
/**
* 分割函數:選擇基準點並將陣列分為兩部分
* @param {number[]} arr - 要分割的陣列
* @param {number} left - 左邊界索引
* @param {number} right - 右邊界索引
* @returns {number} - 基準點的最終索引
*/
function partition(arr, left, right) {
// 選擇最右邊的元素作為基準點
const pivot = arr[right];
// i 表示小於基準點的元素區域的邊界
let i = left - 1;
// 遍歷陣列,將小於基準點的元素移到左邊
for (let j = left; j < right; j++) {
if (arr[j] <= pivot) {
i++;
// 交換 arr[i] 和 arr[j]
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
// 將基準點放到正確位置
[arr[i + 1], arr[right]] = [arr[right], arr[i + 1]];
return i + 1;
}
// 測試程式碼
const array = [64, 34, 25, 12, 22, 11, 90];
console.log("原始陣列:", array);
const sortedArray = quickSort(array);
console.log("排序後陣列:", sortedArray);
程式碼說明
-
quickSort 函數:
-
接受三個參數:arr(要排序的陣列)、left(左邊界索引,預設為 0)、right(右邊界索引,預設為陣列長度減 1)。
-
檢查是否需要繼續遞迴(如果 left >= right 則停止)。
-
調用 partition 函數取得基準點索引,並遞迴排序左右兩部分。
-
-
partition 函數:
-
選擇陣列最右邊的元素作為基準點(pivot)。
-
使用兩個指針 i 和 j:
-
i 追蹤小於基準點的元素區域的右邊界。
-
j 遍歷陣列,尋找小於或等於基準點的元素。
-
-
當找到小於基準點的元素時,交換 arr[i] 和 arr[j]。
-
最後將基準點放到正確位置(i + 1),並返回基準點索引。
-
-
交換元素:
- 使用 ES6 的解構賦值 [arr[i], arr[j]] = [arr[j], arr[i]] 來交換陣列中的兩個元素。
-
測試程式碼:
-
創建一個測試陣列 [64, 34, 25, 12, 22, 11, 90]。
-
輸出原始陣列和排序後的結果。
-
如何運行程式碼
-
將以上程式碼複製到一個 .js 文件(例如 quickSort.js)。
-
在終端機或瀏覽器控制台中使用 Node.js 運行:
node quickSort.js
-
預期輸出:
原始陣列: [64, 34, 25, 12, 22, 11, 90]
排序後陣列: [11, 12, 22, 25, 34, 64, 90]
逐步操作指南
-
理解基準點選擇:
- 這裡選擇陣列的最後一個元素作為基準點(pivot)。你也可以選擇第一個元素或隨機元素,但需要調整 partition 函數的邏輯。
-
分割過程:
-
partition 函數將陣列分為兩部分:小於等於基準點的元素在左邊,大於基準點的元素在右邊。
-
通過交換元素,確保基準點最終位於正確的排序位置。
-
-
遞迴排序:
- 對基準點左邊和右邊的子陣列分別進行快速排序,直到子陣列只剩一個元素或空。