Files
demo-workflow-repo/js/quicksort.js
2025-08-06 09:15:58 +08:00

176 lines
4.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 快速排序算法实现
* 时间复杂度: 平均 O(n log n), 最坏 O(n²)
* 空间复杂度: O(log n)
*/
/**
* 快速排序主函数
* @param {Array} arr - 要排序的数组
* @returns {Array} - 排序后的数组
*/
function quickSort(arr) {
// 如果数组长度小于等于1直接返回
if (arr.length <= 1) {
return arr;
}
// 选择基准值(这里选择最后一个元素)
const pivot = arr[arr.length - 1];
const left = [];
const right = [];
// 将数组分成两部分
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i] <= pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
// 递归排序左右两部分,并合并结果
return [...quickSort(left), pivot, ...quickSort(right)];
}
/**
* 原地快速排序(优化版本,节省空间)
* @param {Array} arr - 要排序的数组
* @param {number} low - 起始索引
* @param {number} high - 结束索引
*/
function quickSortInPlace(arr, low = 0, high = arr.length - 1) {
if (low < high) {
const pivotIndex = partition(arr, low, high);
quickSortInPlace(arr, low, pivotIndex - 1);
quickSortInPlace(arr, pivotIndex + 1, high);
}
return arr;
}
/**
* 分区函数
* @param {Array} arr - 数组
* @param {number} low - 起始索引
* @param {number} high - 结束索引
* @returns {number} - 基准值的最终位置
*/
function partition(arr, low, high) {
// 选择最后一个元素作为基准值
const pivot = arr[high];
let i = low - 1; // 小于基准值的元素的最后位置
for (let j = low; j < high; j++) {
// 如果当前元素小于等于基准值
if (arr[j] <= pivot) {
i++;
// 交换元素
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
// 将基准值放到正确的位置
[arr[i + 1], arr[high]] = [arr[high], arr[i + 1]];
return i + 1;
}
/**
* 三路快速排序(处理重复元素较多的数组)
* @param {Array} arr - 要排序的数组
* @param {number} low - 起始索引
* @param {number} high - 结束索引
*/
function quickSortThreeWay(arr, low = 0, high = arr.length - 1) {
if (low < high) {
const [lt, gt] = partitionThreeWay(arr, low, high);
quickSortThreeWay(arr, low, lt - 1);
quickSortThreeWay(arr, gt + 1, high);
}
return arr;
}
/**
* 三路分区函数
* @param {Array} arr - 数组
* @param {number} low - 起始索引
* @param {number} high - 结束索引
* @returns {Array} - [lt, gt] 小于和大于基准值的边界
*/
function partitionThreeWay(arr, low, high) {
const pivot = arr[low];
let lt = low; // 小于基准值的右边界
let gt = high; // 大于基准值的左边界
let i = low + 1; // 当前扫描位置
while (i <= gt) {
if (arr[i] < pivot) {
[arr[lt], arr[i]] = [arr[i], arr[lt]];
lt++;
i++;
} else if (arr[i] > pivot) {
[arr[gt], arr[i]] = [arr[i], arr[gt]];
gt--;
} else {
i++;
}
}
return [lt, gt];
}
// 测试函数
function testQuickSort() {
console.log("=== 快速排序算法测试 ===");
// 测试数据
const testCases = [
[64, 34, 25, 12, 22, 11, 90],
[5, 2, 4, 6, 1, 3],
[1],
[],
[3, 3, 3, 3, 3],
[9, 8, 7, 6, 5, 4, 3, 2, 1],
[1, 2, 3, 4, 5, 6, 7, 8, 9]
];
testCases.forEach((testCase, index) => {
console.log(`\n测试用例 ${index + 1}:`);
console.log(`原始数组: [${testCase}]`);
// 测试标准快速排序
const sorted1 = quickSort([...testCase]);
console.log(`标准快排: [${sorted1}]`);
// 测试原地快速排序
const arr2 = [...testCase];
quickSortInPlace(arr2);
console.log(`原地快排: [${arr2}]`);
// 测试三路快速排序
const arr3 = [...testCase];
quickSortThreeWay(arr3);
console.log(`三路快排: [${arr3}]`);
});
}
// 导出函数供其他模块使用
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
quickSort,
quickSortInPlace,
quickSortThreeWay,
partition,
partitionThreeWay
};
}
// 如果直接在浏览器中运行,执行测试
if (typeof window !== 'undefined') {
// 将函数添加到全局作用域
window.quickSort = quickSort;
window.quickSortInPlace = quickSortInPlace;
window.quickSortThreeWay = quickSortThreeWay;
// 自动运行测试
testQuickSort();
}