合并排序——一个不重要的变化抛出SystemInvalidOperationException
本文关键字:变化 重要的 SystemInvalidOperationException 不重要 排序 合并 一个 | 更新日期: 2023-09-27 18:07:05
我的程序中发生了一件非常奇怪的事情。下面是简化后的代码:
class Program
{
static void Main(string[] args)
{
ArrayList numbers = new ArrayList();
numbers.Add(1);
numbers.Add(3);
numbers.Add(4);
numbers.Add(2);
var it = Sorts.MergeSort((ArrayList)numbers.Clone());
Sorts.PrintArray(it, "mergesort");
Console.WriteLine("DONE");
Console.ReadLine();
}
}
public static class Sorts
{
public static ArrayList BubbleSort(ArrayList numbers)
{
bool sorted = true;
for (int i = 0; i < numbers.Count; i++)
{
for (int j = 1; j < numbers.Count; j++)
{
if ((int)numbers[j - 1] > (int)numbers[j])
{
int tmp = (int)numbers[j - 1];
numbers[j - 1] = numbers[j];
numbers[j] = tmp;
sorted = false;
}
}
if (sorted)
{
return numbers;
}
}
return numbers;
}
public static ArrayList MergeSort(ArrayList numbers, int switchLimit = 3)
{
//if I use this if - everything works
if (numbers.Count <= 1)
{
// return numbers;
}
//the moment I use this condition - it throws SystemInvalidOperationException in function Merge in the line of a "for"-loop
if (numbers.Count <=switchLimit)
{
return Sorts.BubbleSort(numbers);
}
ArrayList ret = new ArrayList();
int middle = numbers.Count / 2;
ArrayList L = numbers.GetRange(0, middle);
ArrayList R = numbers.GetRange(middle, numbers.Count - middle);
L = MergeSort(L);
R = MergeSort(R);
return Merge(L, R);
}
private static ArrayList Merge(ArrayList L, ArrayList R)
{
ArrayList ret = new ArrayList();
int l = 0;
int r = 0;
for (int i = 0; i < L.Count + R.Count; i++)
{
if (l == L.Count)
{
ret.Add(R[r++]);
}
else if (r == R.Count)
{
ret.Add(L[l++]);
}
else if ((int)L[l] < (int)R[r])
{
ret.Add(L[l++]);
}
else
{
ret.Add(R[r++]);
}
}
return ret;
}
//---------------------------------------------------------------------------------
public static void PrintArray(ArrayList arr, string txt = "", int sleep = 0)
{
Console.WriteLine("{1}({0}): ", arr.Count, txt);
for (int i = 0; i < arr.Count; i++)
{
Console.WriteLine(arr[i].ToString().PadLeft(10));
}
Console.WriteLine();
System.Threading.Thread.Sleep(sleep);
}
}
我的排序有问题。归并排序的功能。当我正常使用它时(看看函数中的第一个if条件),一切都工作得很好。但是,当我希望它以较小的输入切换到bubblessort(函数中的第二个if条件)时,它会向我抛出SystemInvalidOperationException。我不知道问题出在哪里。你看到了吗?谢谢。:)注:bubblesort本身工作-所以不应该有这样的问题…
问题是您使用GetRange
:
此方法不创建元素的副本。新的数组列表只是源数组列表的一个视图窗口。但是,对源数组列表的所有后续更改必须通过该视图窗口完成。如果直接对源数组列表进行了更改,则视图窗口的数组列表无效,并且对其进行的任何操作都会返回InvalidOperationException。
您正在原始ArrayList
上创建两个视图,并尝试使用它们-但是当一个视图修改底层列表时,另一个视图实际上无效。
如果您更改代码以创建子列表的副本-或者如果您在指定的范围内直接使用原始列表-那么我相信它会工作得很好。
(正如在注释中所指出的,我还强烈建议您使用泛型集合)
下面是一个简短但完整的程序,它演示了你遇到的问题:
using System;
using System.Collections;
class Program
{
static void Main()
{
ArrayList list = new ArrayList();
list.Add("a");
list.Add("b");
ArrayList view1 = list.GetRange(0, 1);
ArrayList view2 = list.GetRange(1, 1);
view1[0] = "c";
Console.WriteLine(view2[0]); // Throws an exception
}
}
在这行R = MergeSort(R);
中,您更改了l所表示的数字范围,这使l无效,对不起,我必须走了,所以现在无法进一步解释