From 7721223a7466c50b692640b1f609c07357276a69 Mon Sep 17 00:00:00 2001 From: sgx <1186819569@qq.com> Date: Wed, 6 Aug 2025 09:15:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BF=AB=E9=80=9F=E6=8E=92?= =?UTF-8?q?=E5=BA=8F=E7=AE=97=E6=B3=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/quicksort.js | 176 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 js/quicksort.js diff --git a/js/quicksort.js b/js/quicksort.js new file mode 100644 index 0000000..f944965 --- /dev/null +++ b/js/quicksort.js @@ -0,0 +1,176 @@ +/** + * 快速排序算法实现 + * 时间复杂度: 平均 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(); +} \ No newline at end of file