【问题标题】:TreeView control and NonrecursionTreeView 控件和非递归
【发布时间】:2010-09-02 18:30:50
【问题描述】:

我可以通过递归地枚举注册表项并将它们放入 TreeView 控件中来用特定的注册表项填充 TreeView 控件;然后出于性能原因,我尝试 使用非递归/迭代方法来枚举注册表项,但是我如何填充 TreeView,因为“树”是自然递归的(至少,在我的理解中)?递归是实现它的唯一方法吗?有人会给出一些代码 sn-ps/examples 或将我重定向到网页来解释这个问题吗?

顺便说一句,我是一个 Delphi/Free Pascal 程序员,但是 C/C++ 编程语言解释应该没有问题。干杯:-)

I have asked about this on the Free Pascal mailing list, too.

提前致谢。

【问题讨论】:

    标签: c++ c delphi pascal


    【解决方案1】:

    首先,当您从注册表读取数据并将数据放入树控件时担心递归的“性能”听起来有点傻。递归的成本在纳秒范围内,而从注册表读取的成本在微秒到毫秒范围内。插入树控件的成本取决于可见性和它包含的项目数量,但它通常更接近注册表的范围而不是递归的范围。如果您要在控件中插入大量项目,通常需要锁定控件,使其在插入期间不更新,然后在完成后重新打开更新。

    第二,是的,它可以在没有递归的情况下完成。通常的方法是使用某种容器来保存需要处理的数据,例如队列或堆栈。当您遍历注册表树时,您检索数据,并且当/如果您在树中遇到“子目录”时,您将其推送到堆栈上。当你完成当前的“目录”时,你从堆栈/队列/任何东西中检索下一个并以相同的方式处理它。当集合为空时,您就完成了。

    【讨论】:

    • 感谢 Jerry 的回答,但性能并不是唯一的原因。请参阅我对第一个答案的回复。无论如何,感谢您的第二个陈述。 :-)
    • 如果您使用 BeginUpdate/EndUpdate,任何种类的 Tree/ListView VCL 控件都会有更好的性能。对于任何考虑这个的人来说,只是把这个提示扔在那里。
    【解决方案2】:

    如果性能是问题,请考虑延迟填充 TreeView。从创建树的顶层开始。仅当用户展开树时才填充树的每个下一级。这也应该解决堆栈溢出问题。

    Here您可以找到本机注册表编辑器项目的源代码,您可以将其用作示例。

    【讨论】:

    • 感谢 Lyadvinsky 的快速回复,这是一个不错的项目,我会看看;但是递归有一些噩梦,例如: - OS 平台之间的默认堆栈大小不同。 - 超深递归会触发堆栈溢出异常。这就是为什么我想用非递归/迭代方法重构递归部分。
    • "延迟填充 TreeView" + Delphi = VirtualTreeView :-) (soft-gems.netcode.google.com/p/virtual-treeview)
    • 可以在不占用堆栈空间的情况下进行递归。优化编译器能够将某些类型的递归完成到有效的非递归循环中。但是,您的代码必须以某种方式编写才能实现。我现在不记得具体的细节,但我在 StackOverflow 和其他网站上看到了更详细描述它的讨论。
    • 对于导致堆栈溢出的“超深”递归,@MrBA,深度必须在数百级的数量级,如果不是数千级的话。你的堆栈至少是一兆字节;你的堆栈帧中有多少字节?您见过注册表项嵌套多深?
    • @Remy,您知道执行此类优化的任何 Delphi 或 Pascal 编译器吗?
    猜你喜欢
    • 2013-02-20
    • 2011-02-04
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多