我在以下代码中遇到2个列表时出现问题:
internal class Program
{
private static readonly List<char[]> permutations = new List<char[]>();
private static void Main()
{
string str = "0123456789";
char[] arr = str.ToCharArray();
GetPer(arr);
//2. here we have lost all the values
Console.ReadKey();
}
private static void Swap(ref char a, ref char b)
{
if (a == b) return;
a ^= b;
b ^= a;
a ^= b;
}
public static void GetPer(char[] list)
{
int x = list.Length - 1;
GetPer(list, 0, x);
}
private static void GetPer(char[] list, int k, int m)
{
if (k == m)
{
permutations.Add(list); //1. here we add value to the list
}
else
for (int i = k; i <= m; i++)
{
Swap(ref list[k], ref list[i]);
GetPer(list, k + 1, m);
Swap(ref list[k], ref list[i]);
}
}
}
第一个是void GetPer
中有两条评论,我们在列表中添加了值。第二条评论位于void Main
,我们丢失了之前的所有值。如果需要任何解释,代码主要是从Listing all permutations of a string/integer复制粘贴的。如何避免此引用类型问题?
答案 0 :(得分:3)
您正在反复添加对同一列表的引用。您复制的方法交换两个值,递归运行另一个排列,然后将它们交换回来。最终,在您完成所有排列之后,列表将返回到它开始的位置。
原始程序只是将排列编写到控制台,因此每次排列后更改都被解开并不重要。如果在将结果添加到结果中时复制列表,则应该看到所有排列:
private static void GetPer(char[] list, int k, int m)
{
if (k == m)
{
permutations.Add((char[])(list.Clone())); //1. here we add a clone of the value to the list
}
else
for (int i = k; i <= m; i++)
{
Swap(ref list[k], ref list[i]);
GetPer(list, k + 1, m);
Swap(ref list[k], ref list[i]);
}
}
我会注意到我发现这不是正在阅读“你的”代码,而是通过调试它。策略性地设置断点和手表使这样的问题更容易解决。调试是理解代码中问题的宝贵技能,尤其是您没有编写的代码。
答案 1 :(得分:0)
您可以从 this 回答中学习,所有数组都是引用类型。
这意味着,当您将数组添加到此行代码中的数组列表时:
permutations.Add(list);
您实际上是一遍又一遍地添加相同的数组。由于每次都来回交换该数组中的值,您将获得对同一个精确数组的引用列表。
如果我理解正确,你想在你创建的第一个数组中列出所有可能的字符顺序。
为此,您需要 克隆 您的数组,而不是使用相同的引用。
您应该将添加到收集行更改为:
permutations.Add((char[])list.Clone());
这样,你不是添加相同的引用,而是它的克隆,你的最终列表将充满不同的数组。