|
@@ -0,0 +1,141 @@
|
|
|
+/**
|
|
|
+ * 排序工具函数集合
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * 比较函数类型定义
|
|
|
+ * T 是要比较的元素类型
|
|
|
+ * 返回负数表示 a < b,0 表示 a = b,正数表示 a > b
|
|
|
+ */
|
|
|
+type CompareFunction<T> = (a: T, b: T) => number;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 默认比较函数,用于数字或字符串比较
|
|
|
+ */
|
|
|
+const defaultCompare = <T>(a: T, b: T): number => {
|
|
|
+ if (a < b) return -1;
|
|
|
+ if (a > b) return 1;
|
|
|
+ return 0;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * 交换数组中的两个元素
|
|
|
+ * @param arr 要操作的数组
|
|
|
+ * @param i 第一个元素的索引
|
|
|
+ * @param j 第二个元素的索引
|
|
|
+ */
|
|
|
+function swap<T>(arr: T[], i: number, j: number): void {
|
|
|
+ const temp = arr[i];
|
|
|
+ arr[i] = arr[j];
|
|
|
+ arr[j] = temp;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 分区函数 - 快速排序的核心
|
|
|
+ * 选择一个基准值,将小于基准值的元素放在左侧,大于基准值的元素放在右侧
|
|
|
+ * @param arr 要排序的数组
|
|
|
+ * @param left 左边界索引
|
|
|
+ * @param right 右边界索引
|
|
|
+ * @param compare 比较函数
|
|
|
+ * @returns 基准值的最终位置
|
|
|
+ */
|
|
|
+function partition<T>(
|
|
|
+ arr: T[],
|
|
|
+ left: number,
|
|
|
+ right: number,
|
|
|
+ compare: CompareFunction<T>,
|
|
|
+): number {
|
|
|
+ // 选择最右边的元素作为基准值
|
|
|
+ const pivot = arr[right];
|
|
|
+
|
|
|
+ // 初始化小于基准值区域的指针
|
|
|
+ let i = left - 1;
|
|
|
+ //const numbers = [3, 1, 4, 1, 5, 9,8,7, 2, 6];
|
|
|
+ // 遍历当前分区
|
|
|
+ for (let j = left; j < right; j++) {
|
|
|
+ // 如果当前元素小于基准值
|
|
|
+ if (compare(arr[j], pivot) < 0) {
|
|
|
+ // 扩展小于基准值的区域
|
|
|
+ i++;
|
|
|
+ // 将当前元素交换到小于基准值的区域
|
|
|
+ swap(arr, i, j);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将基准值放到正确的位置
|
|
|
+ swap(arr, i + 1, right);
|
|
|
+
|
|
|
+ // 返回基准值的最终位置
|
|
|
+ return i + 1;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 快速排序的递归实现
|
|
|
+ * @param arr 要排序的数组
|
|
|
+ * @param left 左边界索引
|
|
|
+ * @param right 右边界索引
|
|
|
+ * @param compare 比较函数
|
|
|
+ */
|
|
|
+function quickSortRecursive<T>(
|
|
|
+ arr: T[],
|
|
|
+ left: number,
|
|
|
+ right: number,
|
|
|
+ compare: CompareFunction<T>,
|
|
|
+): void {
|
|
|
+ if (left < right) {
|
|
|
+ // 获取基准值的位置
|
|
|
+ const pivotIndex = partition(arr, left, right, compare);
|
|
|
+
|
|
|
+ // 递归排序基准值左侧的元素
|
|
|
+ quickSortRecursive(arr, left, pivotIndex - 1, compare);
|
|
|
+
|
|
|
+ // 递归排序基准值右侧的元素
|
|
|
+ quickSortRecursive(arr, pivotIndex + 1, right, compare);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 快速排序算法
|
|
|
+ * 时间复杂度: 平均 O(n log n), 最坏 O(n²)
|
|
|
+ * 空间复杂度: O(log n) - 递归调用栈的深度
|
|
|
+ *
|
|
|
+ * @param arr 要排序的数组
|
|
|
+ * @param compare 可选的比较函数,默认按自然顺序排序
|
|
|
+ * @returns 排序后的数组(原地排序,返回原数组的引用)
|
|
|
+ */
|
|
|
+export function quickSort<T>(
|
|
|
+ arr: T[],
|
|
|
+ compare: CompareFunction<T> = defaultCompare,
|
|
|
+): T[] {
|
|
|
+ if (arr.length <= 1) {
|
|
|
+ return arr;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 复制数组以避免修改原数组(如果需要的话可以移除此行来实现原地排序)
|
|
|
+ // const result = [...arr];
|
|
|
+
|
|
|
+ // 调用递归版本的快速排序
|
|
|
+ quickSortRecursive(arr, 0, arr.length - 1, compare);
|
|
|
+
|
|
|
+ return arr;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 使用示例:
|
|
|
+ *
|
|
|
+ * // 对数字数组进行排序
|
|
|
+ * const numbers = [3, 1, 4, 1, 5, 9, 2, 6];
|
|
|
+ * quickSort(numbers); // [1, 1, 2, 3, 4, 5, 6, 9]
|
|
|
+ *
|
|
|
+ * // 对对象数组按特定属性排序
|
|
|
+ * const users = [
|
|
|
+ * { name: 'Tom', age: 25 },
|
|
|
+ * { name: 'Jerry', age: 18 },
|
|
|
+ * { name: 'Spike', age: 32 }
|
|
|
+ * ];
|
|
|
+ * quickSort(users, (a, b) => a.age - b.age); // 按年龄升序排序
|
|
|
+ */
|
|
|
+
|
|
|
+const numbers = [3, 1, 4, 1, 5, 9, 8, 7, 2, 6];
|
|
|
+const sortedNumbers = quickSort(numbers); // [1, 1, 2, 3, 4, 5, 6, 9]
|
|
|
+console.log(sortedNumbers);
|