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

我的MergeSort(归并排序)实现输出异常值,问题出在哪里?

问题原因排查
  • 核心触发原因:Merge函数中第一个循环是打印日志的逻辑,执行完后循环变量i已经等于n1,紧接着给left数组赋值的循环判断条件是i < n1,根本不会执行,left数组的所有元素都是未初始化的堆内存垃圾值,就是你看到的怪异数值来源。
  • 索引逻辑错误:给left数组赋值时额外加了start == 0的判断,甚至非0情况还做了start + i -1的偏移,完全不符合归并排序的区间定义:left数组本应该存储原数组[start, mid)区间的元素,不需要额外的偏移判断,错误的索引会导致读取内存非法位置的值。
  • 递归拆分错误:MergeSort函数递归拆分时第二个子数组传参是mid + 1,但你的Merge函数是按左闭右开区间[start, mid)、[mid, end)处理的,传mid +1会跳过mid位置的元素,导致排序结果缺值或者异常。
修正后可运行代码
#include <iostream>
#include <limits>

void Merge(double A[], size_t start, size_t mid, size_t end)
{
    size_t n1 = mid - start;
    size_t n2 = end - mid;
    size_t i = 0;
    size_t j = 0;

    double* left = new double[n1 + 1];
    double* right = new double[n2 + 1];

    // 重置i后做赋值,不和打印逻辑共用迭代后的变量
    for (i = 0; i < n1; i++)
    {
        // 去掉错误偏移判断,直接取对应区间的值
        left[i] = A[start + i];
        // 打印逻辑可放在赋值后执行
        std::cout << left[i] << " ";
    }
    std::cout << std::endl;

    for (j = 0; j < n2; j++)
    {
        right[j] = A[mid + j];
    }

    left[n1] = std::numeric_limits<double>::infinity();
    right[n2] = std::numeric_limits<double>::infinity();

    i = 0;
    j = 0;
    for (size_t k = start; k < end; k++)
    {
        if (left[i] <= right[j])
        {
            A[k] = left[i];
            i++;
        }
        else
        {
            A[k] = right[j];
            j++;
        }
    }

    delete[] left;
    delete[] right;
}

void MergeSort(double A[], size_t start, size_t end)
{
    // 区间长度大于1才需要拆分排序
    if (end - start > 1)
    {
        size_t mid = (start + end) / 2;
        MergeSort(A, start, mid);
        // 第二个子数组从mid开始,不要加1避免跳过元素
        MergeSort(A, mid, end);
        Merge(A, start, mid, end);
    }
}

调用时如果待排序数组长度为len,直接传入MergeSort(arr, 0, len)即可正常执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 14:18:02