在循环内重写递归以仅使用循环

时间:2016-04-14 12:24:03

标签: c# recursion

我现在坐了几个小时就出现了以下问题,我有一个代码,用于计算包装中适合的盒子数量。为此我计算每个包的包装和复选框。

以下是代码:

private bool CalculateOnePackage(Package package, List<Item> workItems, List<Item> packagedItemsList)
{
  if (workItems.Count == 0)
  {
    return true;
  }

  var packages = new List<Package>();
  Item tempItem = null;
  foreach (Item entity in workItems)
  {
    if (/* execude code that changes entity and packages */)
    {
      tempItem = entity;
      break;
    }
  }

  if (tempItem == null)
  {
    return false;
  }

  packagedItemsList.Add(tempItem);
  workItems.Remove(tempItem);

  foreach (var p in packages)
  {
    this.CalculateOnePackage(p, workItems, packagedItemsList);
  }

  return true;
}

如何重写代码才能使用循环?我们遇到的问题是,此代码会导致StackoverflowException

2 个答案:

答案 0 :(得分:1)

您可以使用Queue<-class来避免StackOverFlowException。因此,将包添加到队列中,处理它并在之后将其从中删除。在queue.Count > 0时循环队列。

由于我不知道该方法应该做什么,因此难以展示一个好的例子。也许(用简单的LINQ查询替换你的循环):

private void CalculateOnePackage(Package package, List<Item> workItems)
{
    Queue<Package> packages = new Queue<Package>();
    packages.Enqueue(package);

    while (packages.Count > 0)
    {
        // method ProcessEntity adds package(s) to the queue
        Item entityItem = workItems
            .FirstOrDefault(item => ProcessEntity(item, packages)); 
        // do something with it if entityItem != null
    }
}

答案 1 :(得分:0)

写出类似的东西,但首先你应该调试并修复返回。此外,您的功能不使用Package包。

此外,您的函数不使用内部递归调用的结果。 (它不会返回或使用this.CalculateOnePackage(p,workItems,packagedItemsList);)。在我意识到这一点之后,我停止了重写代码的尝试。但是你可以在下面阅读我的不完整结果:

private bool CalculateOnePackage(Package package0, List<Item> workItems0, List<Item> packagedItemsList0)
    {
        var q = new Queue<Tuple<Package, List<Item>, List<Item>>>();
        q.Enqueue(new Tuple<Package, List<Item>, List<Item>>(package0, workItems0, packagedItemsList0));
        while (q.Count != 0)
        {
            var state = q.Dequeue();
            var package = state.Item1;
            var workItems = state.Item2;
            var packagedItemsList = state.Item3;

            if (workItems.Count == 0)
            {
                return true;
            }

            var packages = new List<Package>();
            Item tempItem = null;
            foreach (Item entity in workItems)
            {
                if (/* execude code that changes entity */)
                {
                    tempItem = entity;
                    break;
                }
            }

            if (tempItem == null)
            {
                return false;
            }

            packagedItemsList.Add(tempItem);
            workItems.Remove(tempItem);

            foreach (var p in packages)
            {
                q.Enqueue(new Tuple<Package, List<Item>, List<Item>>(p, workItems, packagedItemsList));
            }
        }


        return true;
    }