⚡ 引言:让排序飞起来

想象一下一个经验丰富的图书管理员整理书籍:面对少量书籍时使用插入排序快速整理,面对大量书籍时使用归并排序保证效率,遇到特殊情况还会灵活调整策略。这就是排序优化的精髓——因地制宜,选择最优策略!

在实际应用中,纯粹的教科书算法往往不够用。我们需要各种优化技术来应对复杂多样的实际场景,让排序算法在性能、稳定性、内存使用等多个维度达到最佳平衡。

流程图表

关系流向:

1
2
3
4
5
A["基础排序算法"] → B["优化技术"]
B → C["混合排序<br/>Hybrid Sorting"]
B → D["自适应排序<br/>Adaptive Sorting"]
B → E["并行排序<br/>Parallel Sorting"]
B → F["内存优化<br/>Memory Optimization"]

🔄 混合排序(Hybrid Sorting)

混合排序结合多种算法的优势,在不同情况下选择最适合的算法。

Introsort(内省排序)

Introsort 是 C++ STL 中 std::sort 的实现,结合了快速排序、堆排序和插入排序。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
 * Introsort(内省排序)实现
 * 结合快速排序、堆排序和插入排序的优势
 */
public class IntroSort {
    private static final int INSERTION_SORT_THRESHOLD = 16;

    /**
     * 内省排序主函数
     * @param arr 待排序数组
     */
    public static void introSort(int[] arr) {
        if (arr.length <= 1) return;

        int maxDepth = 2 * (int) (Math.log(arr.length) / Math.log(2));
        introSortHelper(arr, 0, arr.length - 1, maxDepth);
    }

    /**
     * 内省排序递归辅助函数
     * @param arr 数组
     * @param low 起始索引
     * @param high 结束索引
     * @param maxDepth 最大递归深度
     */
    private static void introSortHelper(int[] arr, int low, int high, int maxDepth) {
        int size = high - low + 1;

        // 小数组使用插入排序
        if (size <= INSERTION_SORT_THRESHOLD) {
            insertionSort(arr, low, high);
            return;
        }

        // 递归深度过深使用堆排序
        if (maxDepth == 0) {
            heapSort(arr, low, high);
            return;
        }

        // 正常情况使用快速排序
        int pivotIndex = partition(arr, low, high);
        introSortHelper(arr, low, pivotIndex - 1, maxDepth - 1);
        introSortHelper(arr, pivotIndex + 1, high, maxDepth - 1);
    }

    /**
     * 针对子数组的插入排序
     */
    private static void insertionSort(int[] arr, int low, int high) {
        for (int i = low + 1; i <= high; i++) {
            int current = arr[i];
            int j = i - 1;

            while (j >= low && arr[j] > current) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = current;
        }
    }

    /**
     * 针对子数组的堆排序
     */
    private static void heapSort(int[] arr, int low, int high) {
        int size = high - low + 1;

        // 将子数组部分看作独立的堆进行排序
        // 为简化实现,这里创建临时数组
        int[] temp = new int[size];
        System.arraycopy(arr, low, temp, 0, size);

        // 构建堆
        for (int i = size / 2 - 1; i >= 0; i--) {
            heapify(temp, size, i);
        }

        // 提取元素
        for (int i = size - 1; i > 0; i--) {
            swap(temp, 0, i);
            heapify(temp, i, 0);
        }

        // 复制回原数组
        System.arraycopy(temp, 0, arr, low, size);
    }

    /**
     * 堆化操作
     */
    private static void heapify(int[] arr, int n, int i) {
        int largest = i;
        int left = 2 * i + 1;
        int right = 2 * i + 2;

        if (left < n && arr[left] > arr[largest]) {
            largest = left;
        }

        if (right < n && arr[right] > arr[largest]) {
            largest = right;
        }

        if (largest != i) {
            swap(arr, i, largest);
            heapify(arr, n, largest);
        }
    }

    /**
     * 快速排序的分区操作
     */
    private static int partition(int[] arr, int low, int high) {
        // 三数取中法选择基准
        int mid = low + (high - low) / 2;
        if (arr[mid] < arr[low]) swap(arr, low, mid);
        if (arr[high] < arr[low]) swap(arr, low, high);
        if (arr[high] < arr[mid]) swap(arr, mid, high);
        swap(arr, mid, high); // 将中位数放到末尾作为基准

        int pivot = arr[high];
        int i = low - 1;

        for (int j = low; j < high; j++) {
            if (arr[j] <= pivot) {
                i++;
                swap(arr, i, j);
            }
        }

        swap(arr, i + 1, high);
        return i + 1;
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

Timsort(Tim排序)

Timsort 是 Python 和 Java 中使用的排序算法,专门为真实世界的数据设计。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/**
 * Timsort 简化实现
 * 利用数据中已存在的有序性进行优化
 */
public class TimSort {
    private static final int MIN_MERGE = 32;
    private static final int MIN_GALLOP = 7;

    /**
     * Timsort主函数
     */
    public static void timSort(int[] arr) {
        if (arr.length < 2) return;

        int minRun = computeMinRunLength(arr.length);
        List<Run> runs = new ArrayList<>();

        int i = 0;
        while (i < arr.length) {
            // 寻找或创建run
            Run run = findOrCreateRun(arr, i);

            // 如果run太短,扩展它
            if (run.length < minRun) {
                int extendTo = Math.min(i + minRun, arr.length);
                extendRun(arr, run, extendTo);
            }

            runs.add(run);
            i = run.start + run.length;

            // 合并runs以维持栈不变式
            mergeCollapse(arr, runs);
        }

        // 强制合并剩余的runs
        mergeForceCollapse(arr, runs);
    }

    /**
     * 计算最小run长度
     */
    private static int computeMinRunLength(int n) {
        int r = 0;
        while (n >= MIN_MERGE) {
            r |= (n & 1);
            n >>= 1;
        }
        return n + r;
    }

    /**
     * 寻找或创建一个run
     */
    private static Run findOrCreateRun(int[] arr, int start) {
        if (start >= arr.length - 1) {
            return new Run(start, 1, true);
        }

        int end = start + 1;
        boolean ascending = arr[start] <= arr[end];

        if (ascending) {
            // 寻找递增序列
            while (end < arr.length && arr[end - 1] <= arr[end]) {
                end++;
            }
        } else {
            // 寻找递减序列
            while (end < arr.length && arr[end - 1] > arr[end]) {
                end++;
            }
            // 反转递减序列
            reverse(arr, start, end - 1);
            ascending = true;
        }

        return new Run(start, end - start, ascending);
    }

    /**
     * 扩展run到指定长度
     */
    private static void extendRun(int[] arr, Run run, int extendTo) {
        // 使用插入排序扩展run
        for (int i = run.start + run.length; i < extendTo; i++) {
            int current = arr[i];
            int j = i - 1;

            while (j >= run.start && arr[j] > current) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = current;
        }
        run.length = extendTo - run.start;
    }

    /**
     * 合并runs以维持栈不变式
     */
    private static void mergeCollapse(int[] arr, List<Run> runs) {
        while (runs.size() > 1) {
            int n = runs.size();

            // 检查是否需要合并
            if ((n >= 3 && runs.get(n-3).length <= runs.get(n-2).length + runs.get(n-1).length) ||
                (n >= 4 && runs.get(n-4).length <= runs.get(n-3).length + runs.get(n-2).length)) {

                // 合并较小的那对
                if (runs.get(n-3).length < runs.get(n-1).length) {
                    mergeAt(arr, runs, n - 3);
                } else {
                    mergeAt(arr, runs, n - 2);
                }
            } else if (runs.get(n-2).length <= runs.get(n-1).length) {
                mergeAt(arr, runs, n - 2);
            } else {
                break;
            }
        }
    }

    /**
     * 强制合并所有剩余runs
     */
    private static void mergeForceCollapse(int[] arr, List<Run> runs) {
        while (runs.size() > 1) {
            int n = runs.size();
            if (n >= 3 && runs.get(n-3).length < runs.get(n-1).length) {
                mergeAt(arr, runs, n - 3);
            } else {
                mergeAt(arr, runs, n - 2);
            }
        }
    }

    /**
     * 合并指定位置的两个runs
     */
    private static void mergeAt(int[] arr, List<Run> runs, int i) {
        Run run1 = runs.get(i);
        Run run2 = runs.get(i + 1);

        // 执行归并操作
        merge(arr, run1.start, run1.start + run1.length - 1,
              run1.start + run1.length + run2.length - 1);

        // 更新run信息
        run1.length += run2.length;
        runs.remove(i + 1);
    }

    /**
     * 归并两个相邻的有序序列
     */
    private static void merge(int[] arr, int left, int mid, int right) {
        int[] temp = new int[right - left + 1];
        int i = left, j = mid + 1, k = 0;

        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }

        while (i <= mid) temp[k++] = arr[i++];
        while (j <= right) temp[k++] = arr[j++];

        System.arraycopy(temp, 0, arr, left, temp.length);
    }

    /**
     * 反转数组的指定部分
     */
    private static void reverse(int[] arr, int start, int end) {
        while (start < end) {
            swap(arr, start++, end--);
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    /**
     * Run类:表示一个有序序列
     */
    private static class Run {
        int start;
        int length;
        boolean ascending;

        Run(int start, int length, boolean ascending) {
            this.start = start;
            this.length = length;
            this.ascending = ascending;
        }
    }
}

🎯 自适应排序优化

自适应排序能够根据输入数据的特征自动调整策略。

智能排序选择器

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/**
 * 智能排序算法选择器
 * 根据数据特征自动选择最优算法
 */
public class AdaptiveSorter {

    /**
     * 数据特征分析器
     */
    public static class DataAnalyzer {
        private int sortedness;      // 有序度 (0-100)
        private int duplicateRatio;  // 重复元素比例 (0-100)
        private int range;           // 数据范围
        private boolean isSmallSize; // 是否小规模数据

        public DataAnalyzer(int[] arr) {
            analyzeData(arr);
        }

        private void analyzeData(int[] arr) {
            if (arr.length == 0) return;

            // 分析有序度
            analyzeSortedness(arr);

            // 分析重复元素
            analyzeDuplicates(arr);

            // 分析数据范围
            analyzeRange(arr);

            // 判断规模
            isSmallSize = arr.length < 50;
        }

        private void analyzeSortedness(int[] arr) {
            int orderedPairs = 0;
            int totalPairs = arr.length - 1;

            for (int i = 0; i < arr.length - 1; i++) {
                if (arr[i] <= arr[i + 1]) {
                    orderedPairs++;
                }
            }

            sortedness = totalPairs == 0 ? 100 : (orderedPairs * 100) / totalPairs;
        }

        private void analyzeDuplicates(int[] arr) {
            Set<Integer> uniqueElements = new HashSet<>();
            for (int num : arr) {
                uniqueElements.add(num);
            }

            int uniqueCount = uniqueElements.size();
            duplicateRatio = 100 - (uniqueCount * 100) / arr.length;
        }

        private void analyzeRange(int[] arr) {
            int min = Arrays.stream(arr).min().orElse(0);
            int max = Arrays.stream(arr).max().orElse(0);
            range = max - min + 1;
        }

        public void printAnalysis() {
            System.out.println("数据特征分析:");
            System.out.println("  有序度: " + sortedness + "%");
            System.out.println("  重复率: " + duplicateRatio + "%");
            System.out.println("  数据范围: " + range);
            System.out.println("  小规模数据: " + isSmallSize);
        }
    }

    /**
     * 自适应排序主函数
     */
    public static void adaptiveSort(int[] arr) {
        if (arr.length <= 1) return;

        DataAnalyzer analyzer = new DataAnalyzer(arr);
        analyzer.printAnalysis();

        String selectedAlgorithm = selectAlgorithm(analyzer);
        System.out.println("选择算法: " + selectedAlgorithm);

        long startTime = System.nanoTime();
        executeSort(arr, selectedAlgorithm);
        long endTime = System.nanoTime();

        System.out.printf("排序完成,耗时: %.2f ms%n", (endTime - startTime) / 1_000_000.0);
    }

    /**
     * 根据数据特征选择算法
     */
    private static String selectAlgorithm(DataAnalyzer analyzer) {
        // 小规模数据优先使用插入排序
        if (analyzer.isSmallSize) {
            return "插入排序";
        }

        // 高有序度数据使用插入排序或归并排序
        if (analyzer.sortedness > 80) {
            return "插入排序";
        }

        // 小范围整数使用计数排序
        if (analyzer.range <= 1000 && analyzer.range <= analyzer.arr.length * 2) {
            return "计数排序";
        }

        // 高重复率使用三路快排
        if (analyzer.duplicateRatio > 30) {
            return "三路快排";
        }

        // 一般情况使用内省排序
        return "内省排序";
    }

    /**
     * 执行选定的排序算法
     */
    private static void executeSort(int[] arr, String algorithm) {
        switch (algorithm) {
            case "插入排序":
                insertionSort(arr);
                break;
            case "计数排序":
                arr = countingSort(arr);
                break;
            case "三路快排":
                quickSort3Way(arr, 0, arr.length - 1);
                break;
            case "内省排序":
                IntroSort.introSort(arr);
                break;
            default:
                Arrays.sort(arr); // 系统默认排序
        }
    }

    // 各种排序算法的简化实现
    private static void insertionSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            int current = arr[i];
            int j = i - 1;
            while (j >= 0 && arr[j] > current) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = current;
        }
    }

    private static int[] countingSort(int[] arr) {
        if (arr.length == 0) return arr;

        int min = Arrays.stream(arr).min().orElse(0);
        int max = Arrays.stream(arr).max().orElse(0);
        int range = max - min + 1;

        int[] count = new int[range];
        for (int num : arr) {
            count[num - min]++;
        }

        int index = 0;
        for (int i = 0; i < range; i++) {
            while (count[i] > 0) {
                arr[index++] = i + min;
                count[i]--;
            }
        }

        return arr;
    }

    private static void quickSort3Way(int[] arr, int low, int high) {
        if (low >= high) return;

        int[] bounds = partition3Way(arr, low, high);
        quickSort3Way(arr, low, bounds[0] - 1);
        quickSort3Way(arr, bounds[1] + 1, high);
    }

    private static int[] partition3Way(int[] arr, int low, int high) {
        int pivot = arr[low];
        int lt = low, gt = high + 1, i = low + 1;

        while (i < gt) {
            if (arr[i] < pivot) {
                swap(arr, lt++, i++);
            } else if (arr[i] > pivot) {
                swap(arr, i, --gt);
            } else {
                i++;
            }
        }

        return new int[]{lt, gt};
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

🚀 并行排序优化

多线程并行排序能够充分利用多核处理器的性能。

并行归并排序

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
 * 并行归并排序实现
 * 利用多线程加速大数据量排序
 */
public class ParallelMergeSort {
    private static final int THRESHOLD = 10000; // 并行阈值

    /**
     * 并行归并排序主函数
     */
    public static void parallelMergeSort(int[] arr) {
        if (arr.length <= 1) return;

        ForkJoinPool pool = new ForkJoinPool();
        try {
            pool.invoke(new MergeSortTask(arr, 0, arr.length - 1));
        } finally {
            pool.shutdown();
        }
    }

    /**
     * 归并排序任务类
     */
    private static class MergeSortTask extends RecursiveAction {
        private final int[] arr;
        private final int left;
        private final int right;

        public MergeSortTask(int[] arr, int left, int right) {
            this.arr = arr;
            this.left = left;
            this.right = right;
        }

        @Override
        protected void compute() {
            if (right - left + 1 <= THRESHOLD) {
                // 小数组使用串行归并排序
                mergeSort(arr, left, right);
                return;
            }

            int mid = left + (right - left) / 2;

            // 创建子任务
            MergeSortTask leftTask = new MergeSortTask(arr, left, mid);
            MergeSortTask rightTask = new MergeSortTask(arr, mid + 1, right);

            // 并行执行子任务
            leftTask.fork();
            rightTask.compute();
            leftTask.join();

            // 合并结果
            merge(arr, left, mid, right);
        }

        private void mergeSort(int[] arr, int left, int right) {
            if (left >= right) return;

            int mid = left + (right - left) / 2;
            mergeSort(arr, left, mid);
            mergeSort(arr, mid + 1, right);
            merge(arr, left, mid, right);
        }

        private void merge(int[] arr, int left, int mid, int right) {
            int[] temp = new int[right - left + 1];
            int i = left, j = mid + 1, k = 0;

            while (i <= mid && j <= right) {
                if (arr[i] <= arr[j]) {
                    temp[k++] = arr[i++];
                } else {
                    temp[k++] = arr[j++];
                }
            }

            while (i <= mid) temp[k++] = arr[i++];
            while (j <= right) temp[k++] = arr[j++];

            System.arraycopy(temp, 0, arr, left, temp.length);
        }
    }

    /**
     * 性能对比测试
     */
    public static void benchmarkParallelSort() {
        int[] sizes = {100000, 500000, 1000000, 5000000};

        System.out.println("并行排序性能对比:");
        System.out.println("数据规模\t串行时间\t并行时间\t加速比");
        System.out.println("-".repeat(50));

        for (int size : sizes) {
            int[] data1 = generateRandomArray(size);
            int[] data2 = data1.clone();

            // 串行排序
            long start = System.nanoTime();
            Arrays.sort(data1);
            long serialTime = System.nanoTime() - start;

            // 并行排序
            start = System.nanoTime();
            parallelMergeSort(data2);
            long parallelTime = System.nanoTime() - start;

            double speedup = (double) serialTime / parallelTime;

            System.out.printf("%d\t%.2f ms\t%.2f ms\t%.2fx%n",
                            size,
                            serialTime / 1_000_000.0,
                            parallelTime / 1_000_000.0,
                            speedup);
        }
    }

    private static int[] generateRandomArray(int size) {
        Random random = new Random(42);
        int[] arr = new int[size];
        for (int i = 0; i < size; i++) {
            arr[i] = random.nextInt(size * 10);
        }
        return arr;
    }
}

并行快速排序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
 * 并行快速排序实现
 */
public class ParallelQuickSort {
    private static final int THRESHOLD = 5000;

    public static void parallelQuickSort(int[] arr) {
        if (arr.length <= 1) return;

        ForkJoinPool pool = new ForkJoinPool();
        try {
            pool.invoke(new QuickSortTask(arr, 0, arr.length - 1));
        } finally {
            pool.shutdown();
        }
    }

    private static class QuickSortTask extends RecursiveAction {
        private final int[] arr;
        private final int low;
        private final int high;

        public QuickSortTask(int[] arr, int low, int high) {
            this.arr = arr;
            this.low = low;
            this.high = high;
        }

        @Override
        protected void compute() {
            if (high - low + 1 <= THRESHOLD) {
                quickSort(arr, low, high);
                return;
            }

            int pivotIndex = partition(arr, low, high);

            QuickSortTask leftTask = new QuickSortTask(arr, low, pivotIndex - 1);
            QuickSortTask rightTask = new QuickSortTask(arr, pivotIndex + 1, high);

            leftTask.fork();
            rightTask.compute();
            leftTask.join();
        }

        private void quickSort(int[] arr, int low, int high) {
            if (low < high) {
                int pivotIndex = partition(arr, low, high);
                quickSort(arr, low, pivotIndex - 1);
                quickSort(arr, pivotIndex + 1, high);
            }
        }

        private int partition(int[] arr, int low, int high) {
            int pivot = arr[high];
            int i = low - 1;

            for (int j = low; j < high; j++) {
                if (arr[j] <= pivot) {
                    i++;
                    swap(arr, i, j);
                }
            }

            swap(arr, i + 1, high);
            return i + 1;
        }

        private void swap(int[] arr, int i, int j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
}

💾 内存优化技术

内存优化技术能够减少内存使用,提高缓存效率。

原地归并排序

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/**
 * 原地归并排序实现
 * 减少额外内存使用
 */
public class InPlaceMergeSort {

    /**
     * 原地归并排序主函数
     */
    public static void inPlaceMergeSort(int[] arr) {
        if (arr.length <= 1) return;
        mergeSortHelper(arr, 0, arr.length - 1);
    }

    private static void mergeSortHelper(int[] arr, int left, int right) {
        if (left >= right) return;

        int mid = left + (right - left) / 2;
        mergeSortHelper(arr, left, mid);
        mergeSortHelper(arr, mid + 1, right);
        inPlaceMerge(arr, left, mid, right);
    }

    /**
     * 原地合并两个有序子数组
     * 使用循环位移的方法
     */
    private static void inPlaceMerge(int[] arr, int left, int mid, int right) {
        int start2 = mid + 1;

        // 如果已经有序,直接返回
        if (arr[mid] <= arr[start2]) {
            return;
        }

        while (left <= mid && start2 <= right) {
            if (arr[left] <= arr[start2]) {
                left++;
            } else {
                int value = arr[start2];
                int index = start2;

                // 将元素向右移动
                while (index != left) {
                    arr[index] = arr[index - 1];
                    index--;
                }

                arr[left] = value;

                // 更新所有指针
                left++;
                mid++;
                start2++;
            }
        }
    }

    /**
     * 使用块交换优化的原地归并
     */
    public static void inPlaceMergeSortOptimized(int[] arr) {
        if (arr.length <= 1) return;
        mergeSortOptimizedHelper(arr, 0, arr.length - 1);
    }

    private static void mergeSortOptimizedHelper(int[] arr, int left, int right) {
        if (left >= right) return;

        int mid = left + (right - left) / 2;
        mergeSortOptimizedHelper(arr, left, mid);
        mergeSortOptimizedHelper(arr, mid + 1, right);
        blockSwapMerge(arr, left, mid, right);
    }

    /**
     * 使用块交换的原地归并
     */
    private static void blockSwapMerge(int[] arr, int left, int mid, int right) {
        int leftLen = mid - left + 1;
        int rightLen = right - mid;

        if (leftLen == 0 || rightLen == 0) return;

        // 使用二分查找和块交换进行优化
        if (leftLen <= rightLen) {
            blockSwapMergeHelper(arr, left, mid + 1, leftLen, rightLen);
        } else {
            // 翻转两个子数组,然后递归处理
            reverse(arr, left, mid);
            reverse(arr, mid + 1, right);
            reverse(arr, left, right);
            blockSwapMergeHelper(arr, left, left + rightLen, rightLen, leftLen);
        }
    }

    private static void blockSwapMergeHelper(int[] arr, int left1, int left2, int len1, int len2) {
        if (len1 == 0 || len2 == 0) return;

        if (len1 == 1 && len2 == 1) {
            if (arr[left1] > arr[left2]) {
                swap(arr, left1, left2);
            }
            return;
        }

        int mid1 = len1 / 2;
        int pos = binarySearch(arr, left2, left2 + len2 - 1, arr[left1 + mid1]);

        // 计算新的长度
        int newLen2 = pos - left2;
        int newLen1 = len2 - newLen2;

        // 块交换
        blockSwap(arr, left1 + mid1, left2, newLen2);

        // 递归处理
        blockSwapMergeHelper(arr, left1, left1 + mid1, mid1, newLen2);
        blockSwapMergeHelper(arr, left1 + mid1 + newLen2, pos, len1 - mid1, newLen1);
    }

    private static int binarySearch(int[] arr, int left, int right, int target) {
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }

    private static void blockSwap(int[] arr, int start1, int start2, int len) {
        for (int i = 0; i < len; i++) {
            swap(arr, start1 + i, start2 + i);
        }
    }

    private static void reverse(int[] arr, int start, int end) {
        while (start < end) {
            swap(arr, start++, end--);
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

🔧 排序工具类和框架

通用排序框架

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/**
 * 通用排序框架
 * 提供统一的排序接口和性能监控
 */
public class UniversalSortingFramework {

    /**
     * 排序策略枚举
     */
    public enum SortingStrategy {
        AUTO,           // 自动选择
        QUICK_SORT,     // 快速排序
        MERGE_SORT,     // 归并排序
        HEAP_SORT,      // 堆排序
        INTRO_SORT,     // 内省排序
        TIM_SORT,       // Tim排序
        PARALLEL_MERGE, // 并行归并
        PARALLEL_QUICK  // 并行快排
    }

    /**
     * 排序配置类
     */
    public static class SortingConfig {
        private SortingStrategy strategy = SortingStrategy.AUTO;
        private boolean enableParallel = false;
        private boolean enableProfiling = false;
        private int parallelThreshold = 10000;
        private int insertionSortThreshold = 16;

        // Getters and setters
        public SortingConfig setStrategy(SortingStrategy strategy) {
            this.strategy = strategy;
            return this;
        }

        public SortingConfig enableParallel(boolean enable) {
            this.enableParallel = enable;
            return this;
        }

        public SortingConfig enableProfiling(boolean enable) {
            this.enableProfiling = enable;
            return this;
        }

        public SortingConfig setParallelThreshold(int threshold) {
            this.parallelThreshold = threshold;
            return this;
        }

        public SortingConfig setInsertionSortThreshold(int threshold) {
            this.insertionSortThreshold = threshold;
            return this;
        }
    }

    /**
     * 排序性能统计
     */
    public static class SortingProfile {
        private long executionTime;
        private int comparisons;
        private int swaps;
        private long memoryUsed;
        private String algorithmUsed;

        public void printProfile() {
            System.out.println("排序性能统计:");
            System.out.println("  算法: " + algorithmUsed);
            System.out.println("  执行时间: " + executionTime / 1_000_000.0 + " ms");
            System.out.println("  比较次数: " + comparisons);
            System.out.println("  交换次数: " + swaps);
            System.out.println("  内存使用: " + memoryUsed / 1024.0 + " KB");
        }

        // Getters and setters
        public long getExecutionTime() { return executionTime; }
        public void setExecutionTime(long executionTime) { this.executionTime = executionTime; }
        public int getComparisons() { return comparisons; }
        public void setComparisons(int comparisons) { this.comparisons = comparisons; }
        public int getSwaps() { return swaps; }
        public void setSwaps(int swaps) { this.swaps = swaps; }
        public long getMemoryUsed() { return memoryUsed; }
        public void setMemoryUsed(long memoryUsed) { this.memoryUsed = memoryUsed; }
        public String getAlgorithmUsed() { return algorithmUsed; }
        public void setAlgorithmUsed(String algorithmUsed) { this.algorithmUsed = algorithmUsed; }
    }

    /**
     * 统一排序接口
     */
    public static SortingProfile sort(int[] arr, SortingConfig config) {
        if (arr.length <= 1) {
            SortingProfile profile = new SortingProfile();
            profile.setAlgorithmUsed("无需排序");
            profile.setExecutionTime(0);
            return profile;
        }

        SortingProfile profile = new SortingProfile();
        long startTime = System.nanoTime();
        long startMemory = getUsedMemory();

        // 选择排序策略
        SortingStrategy strategy = selectStrategy(arr, config);
        profile.setAlgorithmUsed(strategy.toString());

        // 执行排序
        executeSorting(arr, strategy, config);

        long endTime = System.nanoTime();
        long endMemory = getUsedMemory();

        profile.setExecutionTime(endTime - startTime);
        profile.setMemoryUsed(Math.max(0, endMemory - startMemory));

        if (config.enableProfiling) {
            profile.printProfile();
        }

        return profile;
    }

    /**
     * 选择排序策略
     */
    private static SortingStrategy selectStrategy(int[] arr, SortingConfig config) {
        if (config.strategy != SortingStrategy.AUTO) {
            return config.strategy;
        }

        // 自动选择策略
        if (arr.length < config.insertionSortThreshold) {
            return SortingStrategy.QUICK_SORT; // 小数组使用快排(包含插入排序优化)
        }

        if (config.enableParallel && arr.length > config.parallelThreshold) {
            return SortingStrategy.PARALLEL_MERGE;
        }

        // 分析数据特征
        AdaptiveSorter.DataAnalyzer analyzer = new AdaptiveSorter.DataAnalyzer(arr);

        if (analyzer.sortedness > 80) {
            return SortingStrategy.TIM_SORT;
        }

        if (analyzer.duplicateRatio > 30) {
            return SortingStrategy.QUICK_SORT; // 使用三路快排变种
        }

        return SortingStrategy.INTRO_SORT;
    }

    /**
     * 执行排序
     */
    private static void executeSorting(int[] arr, SortingStrategy strategy, SortingConfig config) {
        switch (strategy) {
            case QUICK_SORT:
                quickSort(arr, 0, arr.length - 1);
                break;
            case MERGE_SORT:
                mergeSort(arr, 0, arr.length - 1);
                break;
            case HEAP_SORT:
                heapSort(arr);
                break;
            case INTRO_SORT:
                IntroSort.introSort(arr);
                break;
            case TIM_SORT:
                TimSort.timSort(arr);
                break;
            case PARALLEL_MERGE:
                ParallelMergeSort.parallelMergeSort(arr);
                break;
            case PARALLEL_QUICK:
                ParallelQuickSort.parallelQuickSort(arr);
                break;
            default:
                Arrays.sort(arr);
        }
    }

    // 简化的排序算法实现(实际应用中应使用完整实现)
    private static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int pi = partition(arr, low, high);
            quickSort(arr, low, pi - 1);
            quickSort(arr, pi + 1, high);
        }
    }

    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[high];
        int i = low - 1;
        for (int j = low; j < high; j++) {
            if (arr[j] <= pivot) {
                i++;
                swap(arr, i, j);
            }
        }
        swap(arr, i + 1, high);
        return i + 1;
    }

    private static void mergeSort(int[] arr, int left, int right) {
        if (left < right) {
            int mid = left + (right - left) / 2;
            mergeSort(arr, left, mid);
            mergeSort(arr, mid + 1, right);
            merge(arr, left, mid, right);
        }
    }

    private static void merge(int[] arr, int left, int mid, int right) {
        int[] temp = new int[right - left + 1];
        int i = left, j = mid + 1, k = 0;

        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }

        while (i <= mid) temp[k++] = arr[i++];
        while (j <= right) temp[k++] = arr[j++];

        System.arraycopy(temp, 0, arr, left, temp.length);
    }

    private static void heapSort(int[] arr) {
        int n = arr.length;

        for (int i = n / 2 - 1; i >= 0; i--) {
            heapify(arr, n, i);
        }

        for (int i = n - 1; i > 0; i--) {
            swap(arr, 0, i);
            heapify(arr, i, 0);
        }
    }

    private static void heapify(int[] arr, int n, int i) {
        int largest = i;
        int left = 2 * i + 1;
        int right = 2 * i + 2;

        if (left < n && arr[left] > arr[largest]) {
            largest = left;
        }

        if (right < n && arr[right] > arr[largest]) {
            largest = right;
        }

        if (largest != i) {
            swap(arr, i, largest);
            heapify(arr, n, largest);
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    private static long getUsedMemory() {
        Runtime runtime = Runtime.getRuntime();
        return runtime.totalMemory() - runtime.freeMemory();
    }
}

🧪 完整测试示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**
 * 排序优化技术综合测试
 */
public class SortingOptimizationTest {
    public static void main(String[] args) {
        System.out.println("=== 排序优化技术综合测试 ===");

        testIntroSort();
        testTimSort();
        testAdaptiveSort();
        testParallelSort();
        testUniversalFramework();
    }

    private static void testIntroSort() {
        System.out.println("\n1. Introsort测试:");

        int[] data = {64, 34, 25, 12, 22, 11, 90, 88, 76, 50, 42};
        System.out.println("原数组: " + Arrays.toString(data));

        IntroSort.introSort(data);
        System.out.println("排序后: " + Arrays.toString(data));
    }

    private static void testTimSort() {
        System.out.println("\n2. Timsort测试:");

        // 测试部分有序的数据
        int[] partiallyOrdered = {1, 2, 3, 7, 4, 5, 6, 10, 8, 9};
        System.out.println("部分有序数据: " + Arrays.toString(partiallyOrdered));

        TimSort.timSort(partiallyOrdered);
        System.out.println("Timsort结果: " + Arrays.toString(partiallyOrdered));
    }

    private static void testAdaptiveSort() {
        System.out.println("\n3. 自适应排序测试:");

        // 测试不同特征的数据
        int[][] testCases = {
            {5, 2, 8, 1, 9, 3, 7, 4, 6},        // 随机数据
            {1, 2, 3, 4, 5, 6, 7, 8, 9},        // 已排序数据
            {1, 1, 2, 2, 3, 3, 4, 4, 5},        // 大量重复
            {9, 8, 7, 6, 5, 4, 3, 2, 1},        // 逆序数据
        };

        String[] descriptions = {"随机数据", "已排序", "大量重复", "逆序数据"};

        for (int i = 0; i < testCases.length; i++) {
            System.out.println("\n测试 " + descriptions[i] + ":");
            AdaptiveSorter.adaptiveSort(testCases[i].clone());
        }
    }

    private static void testParallelSort() {
        System.out.println("\n4. 并行排序性能测试:");

        ParallelMergeSort.benchmarkParallelSort();
    }

    private static void testUniversalFramework() {
        System.out.println("\n5. 通用排序框架测试:");

        int[] testData = generateRandomArray(100000);

        // 测试不同配置
        UniversalSortingFramework.SortingConfig[] configs = {
            new UniversalSortingFramework.SortingConfig()
                .setStrategy(UniversalSortingFramework.SortingStrategy.AUTO)
                .enableProfiling(true),

            new UniversalSortingFramework.SortingConfig()
                .setStrategy(UniversalSortingFramework.SortingStrategy.PARALLEL_MERGE)
                .enableParallel(true)
                .enableProfiling(true),

            new UniversalSortingFramework.SortingConfig()
                .setStrategy(UniversalSortingFramework.SortingStrategy.INTRO_SORT)
                .enableProfiling(true)
        };

        String[] configNames = {"自动选择", "并行归并", "内省排序"};

        for (int i = 0; i < configs.length; i++) {
            System.out.println("\n配置: " + configNames[i]);
            UniversalSortingFramework.sort(testData.clone(), configs[i]);
        }
    }

    private static int[] generateRandomArray(int size) {
        Random random = new Random(42);
        int[] arr = new int[size];
        for (int i = 0; i < size; i++) {
            arr[i] = random.nextInt(size * 10);
        }
        return arr;
    }
}

🎯 总结

排序优化技术将基础排序算法提升到了新的高度:

核心优化策略

  1. 混合排序:结合多种算法优势,因地制宜
  2. 自适应排序:根据数据特征动态选择策略
  3. 并行优化:充分利用多核处理器性能
  4. 内存优化:减少空间复杂度,提高缓存效率

实际应用价值

  • 性能提升:相比基础算法有显著性能改进
  • 鲁棒性强:能够应对各种数据分布情况
  • 资源效率:更好地利用系统资源
  • 可扩展性:支持大规模数据处理

优化原则

  1. 了解数据特征:针对性优化比盲目优化更有效
  2. 平衡权衡:时间、空间、复杂度之间的平衡
  3. 实测验证:理论分析要结合实际测试
  4. 系统整体:考虑整个系统的性能瓶颈

排序优化技术展示了算法工程化的重要性——不仅要理解算法原理,更要懂得如何将算法调优到实际应用的最佳状态。这些优化思想和技术同样适用于其他算法的改进和优化!


下一篇:《数据结构入门教程:二分查找算法详解与Java实现》