1

我正在尝试为一个数字数组生成所有排列并将返回作为列表返回。我假设因为函数是递归的,所以我不能在DoPermute方法本身中声明要返回的 List<>,所以我将 List<> 定义为Permutation. 该类的代码如下所示:

class Permutation
{

    // Constructors

    public Permutation()
    {
    }

    // build permutations of input array

    public void DoPermute(ref byte[] digits, ref int n, ref int i)
    {
        if (i == n)
        {
            long temp = Numbers.JoinDigits(digits);
            Permutations.Add(temp);
        }
        else
        {
            for (int j = i; j < n; j++)
            {
                SwapValues(ref digits, ref i, ref j);
                int temp = i + 1;
                DoPermute(ref digits, ref n, ref temp);
                SwapValues(ref digits, ref i, ref j);
            }
        }
    }

    public List<long> Permutations { get; set; }

}

我正在使用以下行调用代码,但出现错误。

 byte[] num = { 1, 2, 3, 4, 5 };
 int len = num.Length;
 int zero = 0;
 Permutation p = new Permutation();
 p.DoPermute(ref num, ref len, ref zero);
 List<long> permuts = p.Permutations;

但是,如果将DoPermute方法重新声明为静态并Permutations.Add(temp);用简单的替换,Debug.WriteLine(temp);我确实得到了正确的排列列表。

关于我哪里出错的任何建议?

4

3 回答 3

2

首先,您需要在某处创建排列列表:Permutations = new List<long>();.

其次,如果您希望该方法返回列表而不是定义公共属性,您可以这样做:

public static List<long> DoPermute(ref byte[] digits, ref int n, ref int i)
{
    List<long> permuts = new List<long>();
    DoPermuteWorker(permuts, ref digits, ref n, ref i);
    return permuts;
}

private static void DoPermuteWorker(List<long> permuts, ref byte[] digits, ref int n, ref int i)
{
    if (i == n)
    {
        long temp = Numbers.JoinDigits(digits);
        permuts.Add(temp);
    }
    else
    {
        for (int j = i; j < n; j++)
        {
            SwapValues(ref digits, ref i, ref j);
            int temp = i + 1;
            DoPermuteWorker(permuts, ref digits, ref n, ref temp);
            SwapValues(ref digits, ref i, ref j);
        }
    }
}
于 2013-03-10T11:04:13.080 回答
1

您当前的代码因空引用异常而失败,因为您从未实例化列表。您应该在构造函数中这样做。

但是,我更喜欢将其作为静态方法。将属性用于排列列表对我来说是错误的。为了完成这项工作,您需要将排列列表作为参数添加到递归函数中。并且列表需要由调用者实例化。

所以我认为你的函数应该这样声明:

public static void DoPermute(List<long> Permutations, ref byte[] digits, 
    ref int n, ref int i)     

函数内部的代码可以基本保持不变,只要它进行递归调用,只需要传递列表即可。我不会在这里重复你的代码,因为我认为我的意思应该很明显。

于 2013-03-10T10:59:07.640 回答
0

我认为你得到了一个NullReferenceException因为你的列表没有初始化。这段代码应该解决它;

/// <summary>
/// Computes a permutation of ... 
/// </summary>
class Permutation
{

    /// <summary>
    /// Initializes a new instance of the <see cref="Permutation"/> class.
    /// </summary>
    public Permutation()
    {
        Permutations = new List<long>(20); // you can set here your capacity.
    }

    /// <summary>
    /// Builds permutations of a byte array.
    /// </summary>
    /// <param name="digits">The digits</param>
    /// <param name="n">The n</param>
    /// <param name="i">The i</param>
    public void DoPermute(ref byte[] digits, ref int n, ref int i)
    {
        if (i == n)
        {
            long temp = Numbers.JoinDigits(digits);
            Permutations.Add(temp);
        }
        else
        {
            for (int j = i; j < n; j++)
            {
                SwapValues(ref digits, ref i, ref j);
                int temp = i + 1;
                DoPermute(ref digits, ref n, ref temp);
                SwapValues(ref digits, ref i, ref j);
            }
        }
    }

    /// <summary>
    /// Gets the permuation result.
    /// </summary>
    public List<long> Permutations { get; private set; }

}
于 2013-03-10T11:02:49.777 回答