You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

快速排序最坏测试用例生成代码故障排查:基于中间基准的1~N数组构造问题

问题分析与修复方案

首先,咱们先明确核心目标:构造一个包含1~N的数组,让以中间元素为基准的快速排序执行的比较次数最大化。这个最坏情况的构造逻辑方向是对的——每次把当前最大的元素放在区间中间,这样作为基准时需要和左右所有元素比较,再递归处理左右子区间。但你的代码在递归逻辑和元素填充的细节上出了问题,导致无法生成正确的数组。

原代码的主要问题

1. 递归函数的返回值逻辑混乱

你的antiqs函数试图通过返回值传递剩余的最小元素,这种设计完全没必要,反而导致后续填充0的逻辑出错。递归过程中应该直接把元素放到对应位置,而不是留到main函数里补0,这会造成元素重复或者顺序错误。

2. 区间边界处理错误

当区间长度小于2时(也就是只有1个元素或者空区间),你没有直接填充当前应放的元素,而是返回一个值,导致这些位置被初始化为0,后续补值时逻辑混乱。比如N=4时,原代码会生成重复元素,就是这个原因。

3. 数组初始化和填充的冗余操作

初始化数组为0然后补0的方式多余且容易出错,递归过程中应该直接填充所有位置,不需要后续补全。

4. 栈溢出风险

原代码中用int array[n]是变长数组(VLA),当N达到70000时,栈内存会直接溢出,因为栈的容量通常远小于这个规模。

修复后的代码实现

我们重构递归函数,让它直接负责填充当前区间的元素,通过引用跟踪当前要放置的最大元素,同时改用动态数组避免栈溢出:

#include <iostream>
#include <fstream>
using namespace std;

// 递归填充数组:在[start, end]区间构造最坏情况数组
void antiqs(int* array, int start, int end, int& current_max) {
    if (start > end) {
        return; // 空区间,直接返回
    }
    if (start == end) {
        // 单个元素,直接放当前最大的元素
        array[start] = current_max;
        current_max--;
        return;
    }
    // 计算当前区间的中间位置
    int middle = (start + end) / 2;
    // 把当前最大元素放到中间
    array[middle] = current_max;
    current_max--;
    // 递归处理左半区间和右半区间
    antiqs(array, start, middle - 1, current_max);
    antiqs(array, middle + 1, end, current_max);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    ifstream fileIn("antiqs.in.txt");
    fileIn >> n;
    fileIn.close();
    
    int* array = new int[n]; // 动态数组避免栈溢出
    
    int current_max = n;
    antiqs(array, 0, n - 1, current_max);
    
    ofstream fileOut("antiqs.out.txt");
    for (int i = 0; i < n; i++) {
        fileOut << array[i] << " ";
    }
    fileOut.close();
    
    delete[] array; // 释放动态数组内存
    return 0;
}

修复后的关键改进

  1. 递归逻辑简化:递归函数直接填充每个区间的元素,通过引用传递current_max,每次放置后递减,确保每个元素都是1~N的唯一值。
  2. 区间边界正确处理:单独处理空区间和单个元素的情况,直接放置当前最大元素,避免遗漏。
  3. 避免栈溢出:改用动态数组在堆上分配内存,适配N最大70000的场景。
  4. 去掉冗余操作:递归过程中直接填充所有位置,无需再处理0值,彻底避免元素重复或缺失。

测试验证

比如N=4时,修复后的代码生成数组[3,4,2,1]:

  • 第一次基准是4,和3、2、1比较(3次)
  • 左区间无需排序
  • 右区间基准是2,和1比较(1次)
    总比较次数4次,确实是最坏情况。

再比如N=5时,生成数组[4,5,3,1,2]:

  • 基准5,和4、3、1、2比较(4次)
  • 左区间无需排序
  • 右区间基准是3,和1、2比较(2次)
    总比较次数6次,符合最坏情况的要求。

内容的提问来源于stack exchange,提问作者user17109797

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 18:14:09