Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 避免递归中堆栈溢出的技巧_C#_Algorithm_Recursion - Fatal编程技术网

C# 避免递归中堆栈溢出的技巧

C# 避免递归中堆栈溢出的技巧,c#,algorithm,recursion,C#,Algorithm,Recursion,我正在为一个ASP.NET/C网站编写一个算法,该网站为学生、教师和教室制定了时间表。我这样做是通过递归实现的(伪代码): 如您所见,我有一个句柄,确保递归永远不会失控(numberOfTries)。然而,随着时间的推移,该算法必然会尝试很多次,这会导致Stackoverflow异常。有没有关于如何避免这种情况的建议?增加堆栈大小(我不喜欢这个)?在线程中运行计划?我已经在考虑重写整个方法,但只是想看看是否有人能给出一些建议。这个问题是通过远离递归而将其写成一个简单的循环/迭代来解决的。我是这样

我正在为一个ASP.NET/C网站编写一个算法,该网站为学生、教师和教室制定了时间表。我这样做是通过递归实现的(伪代码):


如您所见,我有一个句柄,确保递归永远不会失控(numberOfTries)。然而,随着时间的推移,该算法必然会尝试很多次,这会导致Stackoverflow异常。有没有关于如何避免这种情况的建议?增加堆栈大小(我不喜欢这个)?在线程中运行计划?我已经在考虑重写整个方法,但只是想看看是否有人能给出一些建议。

这个问题是通过远离递归而将其写成一个简单的循环/迭代来解决的。我是这样解决的:

public Booking GetBooking(..., int numberOfTries) {
     while (true)
          numberOfTries--;
          if (numberOfTries == 0) {
               return null;
          }

          if (allResorcesAreAvailable) {
               return new Booking()
          }
     }
}

我应该注意到,从您发布的代码来看,似乎可以使用简单的循环设计

但我将解决实际问题“如何防止递归堆栈溢出”

用递归完成的任何事情都可以用一个简单的
堆栈

使用
堆栈
,您可以将其放在堆上,并对其进行管理,几乎没有任何限制

让我们看看你的代码,看起来像这样

public Booking GetBooking(..., int numberOfTries) 
{
 Stack<BookingStateData> stk = new Stack<BookingStateData>();

 while(!stk.isEmpty())
 {
  BookingStateData current = stk.Pop();

  if (current.allResorcesAreAvailable) {
    return new Booking(current...)
  }

  if(stk.Count > maxDepth) // if you want to limit the DFS Depth
     continue;

  stk.push(new BookingStateData(yada,yada)); // fake recursion.
 }
 return null;
}
公共预订GetBooking(…,整数次)
{
堆栈stk=新堆栈();
而(!stk.isEmpty())
{
bookingstatedatacurrent=stk.Pop();
if(当前所有资源可用){
返回新预订(当前…)
}
if(stk.Count>maxDepth)//如果要限制DFS深度
继续;
stk.push(newbookingstatedata(yada,yada));//伪递归。
}
返回null;
}

补充说明:如果您使用
队列
而不是
堆栈
,则可以使用BFS方法而不是给定的DFS。

递归是一个漂亮且雄辩的想法,但我发现它很难管理。我会重写它,因为我是一个简单的女孩,我喜欢简单,易于维护的代码。我唯一看到的错误是numberOfTries可能没有向上的约束。代码中没有使递归有用的东西。一个简单的循环可以代替这个。这可能只是一个风格上的建议,因为我不知道输入的范围,但是如果你真的需要做递归,不要使用numberOfTries——在开始时,您可以通过将return语句更改为:return GetBooking(…,ref numberOfTries-1)来接近基本情况,以避免在输入为0时出现堆栈溢出。但正如上面的评论所说,从所显示的内容来看,不需要递归。这非常有趣!我只是将代码改为使用简单迭代,程序实际上完成了,尽管这需要花费相当长的时间!有人能告诉我为什么递归对资源的要求如此之高吗?这是因为它每次递归调用生成X个对象,从而以极快的速度窃取资源吗?@nath您是将其编译为64位还是32位?你使用什么版本的.NET?如果我没记错的话,只有4.6版本的64位RyuJit编译器执行尾部递归优化。通常作为for循环编写:
for(int t=0;t
。。。这更容易理解,因为它是有限的。
public Booking GetBooking(..., int numberOfTries) 
{
 Stack<BookingStateData> stk = new Stack<BookingStateData>();

 while(!stk.isEmpty())
 {
  BookingStateData current = stk.Pop();

  if (current.allResorcesAreAvailable) {
    return new Booking(current...)
  }

  if(stk.Count > maxDepth) // if you want to limit the DFS Depth
     continue;

  stk.push(new BookingStateData(yada,yada)); // fake recursion.
 }
 return null;
}