【问题标题】:recursion using only heap area仅使用堆区域的递归
【发布时间】:2011-02-17 22:12:56
【问题描述】:

是否有仅使用堆区域的递归示例?

【问题讨论】:

  • 这不是家庭作业,是吗?
  • @gcc 没必要防备......这看起来像是一个典型的家庭作业问题,如果是,我宁愿不直接回答。如果不是,则没有问题。
  • 没有提及您为什么需要它们的问题通常是家庭作业问题。任何 OP 对于想要确保他们没有做别人的作业的人都应该没问题。

标签: c recursion heap-memory


【解决方案1】:

我是这样做的:

  1. 将队列实现为(对象、状态)对的单链表
  2. 插入一个根(对象,状态)对,指示递归的开始位置

那么……

  1. 对于队列中的每个(对象、状态)节点:
  2. |调用object.Recurse(状态)
  3. |对象处理状态并根据需要将子节点/状态添加到队列中
  4. 移动到下一对直到队列结束

通常,我将其实现为实用程序类“Recursor” 对象实现接口“IRecursable”

可以要求 Recursor 类递归深度优先或宽度优先。

我的实现还在根节点上调用 RecursionBegin() 和 RecursionEnd(),以便被递归的类可以处理所需的任何初始化和清理代码。

递归类也可以让根通知每个被调用的对等点 - 允许它看到:

RecursionBegin() - 在递归开始之前调用一次。
RecursionElement() - 多次调用(可选)。
RecursionEnd() - 在递归结束后调用一次。

这些方法是 IRecursable 接口的一部分,可以被重写以允许类灵活地使用递归器。

但还有更简洁的方法

有时我将这些实用程序移动到一个名为 Recursable 的类中,该类结合了类 Recursor 和接口 IRecursable 的特性......或者将它们完全组合到对象类中,这意味着要递归的类成为自递归的,不需要任何支持类。

希望能帮助某人开始将递归算法转换为基于堆的算法......并避免破坏堆栈或导致讨厌的堆栈溢出

TBH,递归是邪恶的,应该像瘟疫一样避免! (除非您的语言允许真正的尾调用递归)

...尊重堆栈,它是宝贵的资源!!!

【讨论】:

    【解决方案2】:

    是的,可以只使用堆来实现递归,在某些情况下这是非常可取的。例如,请参阅Stackless Python。这样做的主要好处之一是整个线程可以变得可序列化,并且您可以将线程从一个主机传送到另一个主机(即使是不同的架构和操作系统!)。

    【讨论】:

      【解决方案3】:

      为了使函数递归,它必须至少调用一次自身。当它调用自身时,它会在堆栈上放置一个指向自身的指针,以便递归调用返回。当然,栈不是堆,因此不可能实现只使用堆的递归函数。

      (至少,在 C 中不是。函数式语言经过优化以重用堆栈空间,并且不为返回调用分配指针)

      【讨论】:

        【解决方案4】:

        在许多实现中,函数调用的参数存储在堆栈中。诸如要返回的地址之类的信息也可以存储在堆栈中。因此,在不使用堆栈的情况下拥有递归函数可能是不可行的。

        检查您的编译器文档,看看是否可以在不占用堆栈空间的情况下调用函数。如果是这样,你就在路上了。

        【讨论】:

          【解决方案5】:

          您可以做一些疯狂的事情,例如 malloc 一个新区域,关闭中断和几乎所有其他事情(在许多系统上不可能)并将堆栈指针设置为该 malloc 区域。从技术上讲,您仍在使用堆栈,但是该堆栈位置现在在堆上。这样做不是一个好主意,但它可以在您具有这种控制级别的某些嵌入式类型系统上工作。

          【讨论】:

          • 我不确定我是否会购买消除堆栈,但 +1 是为了创意。
          • 我已经在 Palm 上使用它来实现具有深度递归的游戏 AI。
          【解决方案6】:

          在 C 中,基于函数调用的递归总是使用堆栈,几乎按照定义。

          如果您愿意将递归转换为迭代,则可以只使用堆空间,但这并不是真正的递归。您可以通过在堆中实现堆栈来实现。

          某些问题可以使用tail recursion,它会反复覆盖堆栈的同一区域。

          【讨论】:

          • 您可以使用混合方法。调用堆栈仍然用于简单的参数和返回地址,但是像数组和 strcuts 这样的大参数保存在堆分配的堆栈中。因此,您可以在不快速爆炸(调用)堆栈 ti 的情况下获得(相对)深度递归。
          • 并不总是正确的;你可以做一些黑客攻击将堆栈指针重新定位到堆上以进行非常深的递归:gist.github.com/msg555/5418199
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-25
          • 2014-12-10
          • 2016-05-23
          • 2019-04-10
          • 2020-07-21
          • 2014-11-10
          相关资源
          最近更新 更多