C# 合并排序返回所有零

C# 合并排序返回所有零,c#,mergesort,C#,Mergesort,最终合并的输出为[0,0,0,0]。我认为它对于数组左半部分的第一次合并是正确的,因为它正确地排列了顺序。我想帮助调试这个 static public void Main(string[] args) { int[] input = { 4, 1, 3, 2}; MergeSort(input, 0, input.Length - 1); for (int i = 0; i < input.Length; i++) { Console.Wri

最终合并的输出为[0,0,0,0]。我认为它对于数组左半部分的第一次合并是正确的,因为它正确地排列了顺序。我想帮助调试这个

static public void Main(string[] args)
{
    int[] input = { 4, 1, 3, 2};
    MergeSort(input, 0, input.Length - 1);
    for (int i = 0; i < input.Length; i++)
    {
        Console.WriteLine(input[i]);
    }
    Console.ReadLine();
}

static public void MergeSort(int[] input, int left, int right)
{
    if (left < right)
    { 
        int middle = (left + right) / 2;
        MergeSort(input, left, middle);
        MergeSort(input, middle + 1, right);
        Merge(input, left, (middle + 1), right);
    }
}

static public void Merge(int[] input, int left, int middle, int right)
{
    int tempindex = left;
    int[] tmp = new int[input.Length];
    int rightpointer = middle + 1;
    int leftpointer = left; 
    while (leftpointer <= middle && rightpointer <= right)
    {
        if (input[leftpointer] < input[rightpointer])
        {
            tmp[tempindex] = input[leftpointer];
            leftpointer++; 
        }
        else
        {
            tmp[tempindex] = input[rightpointer];
            rightpointer++;
        }
        tempindex++; 
    }
    while (leftpointer <= middle)
    {
        tmp[tempindex] = input[leftpointer];
        leftpointer++; 
        tempindex++;
    }
    while (rightpointer <= right)
    {
        tmp[tempindex] = input[rightpointer];
        right++;
        tempindex++;
    }

    for (int i = 0; i < tmp.Length; i++)
    {
        input[i] = tmp[i];
    }
}
static public void Main(字符串[]args)
{
int[]输入={4,1,3,2};
MergeSort(输入,0,输入.长度-1);
for(int i=0;i虽然(leftpointer略微更改了代码以使其正常工作。请参考一些在线资源以更好地了解该算法

private static void Merge(int[] input, int left, int middle, int right)
    {
        int[] temp = new int[input.Length];
        int rightpointer = middle - 1;
        int tempindex = left;
        int num = right - left + 1;

        while ((left <= rightpointer) && (middle <= right))
        {
            if (input[left] <= input[middle])
            {
                temp[tempindex] = input[left];
                tempindex++;
                left++;
            }
            else
            {
                temp[tempindex] = input[middle];
                tempindex++;
                middle++;
            }
        }

        while (left <= rightpointer)
        {
            temp[tempindex] = input[left];
            tempindex++;
            left++;
        }

        while (middle <= right)
        {
            temp[tempindex] = input[middle];
            tempindex++;
            middle++;
        }

        for (int i = 0; i < num; i++)
        {
            input[right] = temp[right];
            right--;
        }
    }
私有静态无效合并(int[]输入,int左,int中,int右)
{
int[]temp=new int[input.Length];
int rightpointer=middle-1;
int tempindex=左;
int num=右-左+1;

虽然((左而不是简单地发布您的代码的固定版本,我认为这是一个毫无意义和毫无帮助的练习,不会在任何重要方面对您有任何好处,但我将尝试从更高层次的角度解释您的错误,并就如何避免今后出现类似错误提供一些建议

您的代码中有几个问题。它们分为三类:

  • 经典编程错误,在处理索引时,尤其是在处理这些边缘情况的边界值时,应该始终保持警惕
  • 简单的输入错误。另一个典型的编程错误。在这种情况下,很可能是在复制和粘贴
    while
    循环时发生的,然后过度键入错误的变量名。应尽量避免复制/粘贴;在典型的合并排序中,这几乎是不可避免的,因此应遵循推论规则:如果您在复制/粘贴时必须更改粘贴代码中的变量名称,请仔细检查您的工作
  • 概念化。这是“经典”的,因为程序员很难学习好的高级概念化和抽象技能,但它以许多不同的方式表现出来(与前两种不同)我最好的建议是几年前我的一位教授喜欢说的一句话:亲吻,或者“.”或者我喜欢用同样的方式来表达:“懒惰是好的”。无论哪种方式,重点都是尽可能地简化问题。如果必须手动操作,请将数据建模与您希望解决问题的方式保持一致,并确保如果必须手动操作,您将以最简单、最省力的方式进行
  • 那么,这些错误在哪里出现的呢?从最后一个到第一个

    概念上,你的代码中最大的问题是你的<代码> MuGe()//C>方法分配一个全尺寸的数组,它是<代码>输入>代码>数组,即使你确信该方法应该只考虑该数组的一个子集。(你知道,因为这是该方法的其他三个参数的完整点)。

    这导致该方法后来出现了一个问题,因为当您将
    tmp
    数组复制回
    input
    时,您只是盲目地编写了一个循环来复制所有数据。这是因为该方法实际上只将值写入
    tmp
    数组的一个子集。这最终是您的输出全部为零的原因。不是吗
    tmp
    数组中的所有值都已写入,因此它们仍然具有默认值
    0
    ,然后将这些值复制到
    输入
    数组中,覆盖实际需要的原始值

    如果您为
    tmp
    分配了一个数组,该数组的大小仅足以包含您在该特定调用期间实际要处理的数据,那么在最后如何将数据复制回来就非常清楚了。最坏的情况是,您会得到一个
    indexootfrangeexception
    ,这是一种更好的数据复制方法这是原理的一个例子,也是我喜欢的另一个概念

    现在,关于这个错误。坦率地说,一旦你有触发错误的数据,你最终会发现这个错误。事实上,你的输入数据集没有,因为它从来没有进入错误所在的循环。但是,你的上一个
    while
    循环在
    合并()
    方法是增加
    right
    变量,而不是
    rightindex
    变量。一旦
    tempindex
    变量太大,这将导致
    IndexOutOfRangeException
    (因此,至少它会很快失败:)

    FWIW,除了简单地确保在复制/粘贴时对工作进行双重和三重检查外,这是一个例子,说明了为什么在这样的简单循环中,实际上需要使用更简洁的语法,即将增量后表达式放入数组中。这样做可以确保递增的索引确实是ind用于为数组编制索引的ex:

    while (rightpointer <= right)
    {
        tmp[tempindex++] = input[rightpointer++];
    }
    
    最后,我没有写任何关于调试的内容。但实际上,尝试修复代码的第一步是使用调试器逐步完成。在编写代码时,您考虑了预期代码将采取的各种操作和结果。当您调试代码时,您要找的是任何违反这些预期的地方

    如果你仔细阅读了代码,你会发现的第一件事就是
    static public void Main(string[] args)
    {
        int[] input = { 4, 1, 3, 2 };
        MergeSort(input, 0, input.Length - 1);
        for (int i = 0; i < input.Length; i++)
        {
            Console.WriteLine(input[i]);
        }
        Console.ReadLine();
    }
    
    static public void MergeSort(int[] input, int left, int right)
    {
        if (left < right)
        {
            int middle = (left + right) / 2;
            MergeSort(input, left, middle);
            MergeSort(input, middle + 1, right);
    
            // was: Merge(input, left, (middle + 1), right);
            Merge(input, left, middle, right);
        }
    }
    
    static public void Merge(int[] input, int left, int middle, int right)
    {
        // was: int tempindex = left;
        int tempindex = 0;
    
        // was: int[] tmp = new int[input.Length];
        int[] tmp = new int[right - left + 1];
    
        int rightpointer = middle + 1;
        int leftpointer = left;
        while (leftpointer <= middle && rightpointer <= right)
        {
            if (input[leftpointer] < input[rightpointer])
            {
                tmp[tempindex] = input[leftpointer];
                leftpointer++;
            }
            else
            {
                tmp[tempindex] = input[rightpointer];
                rightpointer++;
            }
            tempindex++;
        }
        while (leftpointer <= middle)
        {
            tmp[tempindex] = input[leftpointer];
            leftpointer++;
            tempindex++;
        }
        while (rightpointer <= right)
        {
            tmp[tempindex] = input[rightpointer];
    
            // was: right++;
            rightpointer++;
    
            tempindex++;
        }
    
        for (int i = 0; i < tmp.Length; i++)
        {
            // was: input[i] = tmp[i];
            input[left + i] = tmp[i];
        }
    }