C# 合并排序返回所有零
最终合并的输出为[0,0,0,0]。我认为它对于数组左半部分的第一次合并是正确的,因为它正确地排列了顺序。我想帮助调试这个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
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];
}
}