【问题标题】:C# Recursion Depth - How Deep can you goC#递归深度——你能走多深
【发布时间】:2011-05-29 15:29:02
【问题描述】:

是否可以控制递归调用的次数?

从一个基本的测试程序我得到的递归深度刚刚超过 18k

这取决于堆栈大小....

有没有办法用大量堆栈设置一块内存(可能是一个线程)以增加递归深度?

【问题讨论】:

  • 无限深。或者至少在支持尾调用的语言中。
  • 3 级深...ref>
  • Afaik 抖动不一定需要尾调用指令来重写尾调用。根据我在 .net 3.5 上的回忆,只有 64 位抖动会重写尾调用。
  • 您必须了解 99.99% 的代码不会破坏堆栈,而 99.99% 的代码会破坏堆栈,因为它是无限递归的。只剩下 0.02% 的代码通过使用有限的数量来破坏堆栈。只有这些程序可以通过增加堆栈而受益。
  • 我可以知道你的统计数据的来源吗? :)

标签: c# .net recursion stack


【解决方案1】:

在某些文档识别过程中,我增加了堆栈大小。真的很需要。

因此您可以使用以下代码增加线程的堆栈大小:

var stackSize = 10000000;
Thread thread = new Thread(new ThreadStart(BigRecursion), stackSize);

线程(ThreadStart, Int32) -- 初始化一个新的实例 线程类,指定最大值 线程的堆栈大小。

Source

希望这是你所需要的。

【讨论】:

  • 我真的怀疑这是任何人都需要的。你根本不应该创建这样的代码,我会解雇一个尝试过的程序员。任何递归算法都可以在不使用递归的情况下实现,有时它可以通过将问题的阶数降低一个数量级的方式来实现。这就像汽车修理工用大锤修理发动机一样。
  • @Mick,如果使用递归的代码不在您的控制范围内怎么办?例如,您可能正在使用使用递归的第三方库。
  • 我会找到第四方 ;)
  • 说真的......除非他们是这种实施的例外情况,否则我会对供应商的能力失去信心并且不愿意依赖他们的产品。
  • 仅供参考,问题是一个“可以”,至于“为什么”,有各种原因都不是可解雇的罪行:) 我认为有时人们过于专注于自己的小泡沫以及他们试图实现的目标,他们没有考虑到人们想用编程语言做什么的广阔世界。对你应该做什么和不应该做什么有非常强烈的意见常常会限制你的思考。话虽如此,这是大多数人通常不需要的东西,您应该始终评估您所做的权衡
【解决方案2】:

我认为您在这里冒着问题的风险。很难确定递归算法将使用多少堆栈。而且,如果您对是否足够有疑问,我会寻找另一种方法。

大多数递归算法都可以重写为不递归。然后,您可以根据需要分配尽可能多的内存,如果内存不足,甚至可以优雅地恢复。

【讨论】:

  • +1 每个递归算法都可以写成带有循环和堆栈数据结构的非递归算法。
  • @Byron:谢谢你让我想起了我在大学里的数据结构课。教授:“以非递归格式编写这个树遍历程序。”我:“你为什么讨厌我们?” :)
  • 我的问题是如何做到这一点,我更好奇而不是想要真正做到这一点。虽然这是一个很好的建议,但它并不能回答所提出的问题。
  • 在选择递归时不要忘记这些considerations
【解决方案3】:

默认堆栈大小存储在 PE 标头中。

如果你自己生成线程,Thread 有一个将堆栈大小作为参数的构造函数。

但是,1 MB 的默认 .NET 堆栈大小对于大多数任务来说应该足够了,因此在您更改它之前,您至少应该查看该任务。

【讨论】:

    【解决方案4】:

    即使您设法获得更大的递归深度,出于性能原因,我也会在没有递归的情况下实现此算法。方法调用比 while 循环中的迭代要昂贵得多。我强烈建议不要实现任何需要摆弄默认堆栈大小的东西。

    我偶尔会使用递归,但仅在定义了调用深度且调用深度较低(如小于 100)时使用。在创建商业软件时,使用具有无限次迭代的递归算法是完全不专业的,并且可能会让您非常生气。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-20
      • 1970-01-01
      • 2016-03-02
      • 2011-02-07
      • 2021-10-28
      • 2015-02-28
      • 2010-10-25
      相关资源
      最近更新 更多