从递归函数返回列表

时间:2013-03-10 10:45:55

标签: c#

我正在尝试为数组数组生成所有排列,并将返回值作为List返回。我认为因为函数是递归的,所以我不能声明List<>要在DoPermute方法本身返回,所以我已经定义了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);,我会获得正确的排列列表。

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

3 个答案:

答案 0 :(得分: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);
        }
    }
}

答案 1 :(得分:1)

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

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

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

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

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

答案 2 :(得分: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; }

}