【问题标题】:Count property on tree structure (non-binary)树结构上的计数属性(非二进制)
【发布时间】:2012-10-12 23:07:27
【问题描述】:

我正在实现一个基于 c# 的树数据结构(主要基于 Dan Vanderboom's Generic implementation)。我现在正在考虑处理 Dan 没有实现的 Count 属性的方法。

显而易见且简单的方法是使用递归调用,它可以愉快地遍历树并添加节点(或者如果您愿意,可以使用 Queue 迭代遍历树并计算节点)。只是看起来很贵。 (我也可能想延迟加载我的一些节点)。

我可以在根节点上维护一个计数。所有子节点都将遍历和/或持有对根的引用,并在更改时更新内部可设置的计数属性。这会将迭代问题推到我想要中断分支或清除给定节点下的所有子节点的时候。通常更便宜,并且将繁重的工作放在我认为不常被调用的函数中。

似乎有点蛮力,这通常意味着我还没有想到的异常情况,或者如果您愿意,还有错误。

有没有人有一个实现的例子,它保持一个不平衡和/或非二叉树结构的计数,而不是即时计数?不用担心延迟加载,我相信我可以调整示例以满足我的特定需求。

【问题讨论】:

  • 为什么不使用静态变量并根据需要递增/递减?
  • 静态变量将应用于我的树结构的所有实例。
  • 是的(我的想法太多了)。那为什么不是实例变量呢?
  • 为什么递归调用看起来很昂贵?在我看来,这是看待它的自然方式。
  • @Stanley 谢谢你的意见。我同意有人可以争辩说递归是一种可接受的路径。我只是认为递归会带来一些风险,即使非常小且不太可能。

标签: c# .net data-structures tree


【解决方案1】:

你可以在树上有一个 count 属性。在添加节点的方法中,增加计数,在删除节点的方法中,减少计数。

运行时间 = 读取属性所需的时间。

【讨论】:

  • 在树中,您可以将节点添加到节点。树将如何跟踪这些?
  • 谢谢@SamualDavis。 Dave 准确地指出了我想要解决的问题。
  • 您可以有一个扩展树类的节点类,并允许节点包含节点。每个节点类都有一个计数属性,而树类也有一个计数属性。每次添加一个节点时,父节点计数增加一,树的计数属性也增加一。这样你就可以知道每个节点有多少直接后代,还有多少在树都在一起。但是,如果您希望每个节点都知道它有多少个孩子,那么我的想法就不够了。
  • @SamuelDavis 谢谢。你已经描述了我想要做什么。 Gilfish 下面的建议是类似的。我喜欢。我只想要一个示例实现。
【解决方案2】:

您似乎一直在考虑节点,却忘记了控制对节点的访问的 Tree 类。您的 Tree 类可以有一个 Count 属性,并且由于 Add 和 Remove 都由 Tree 类公开(它们不应该由节点公开),您始终可以在项目更改时对其进行递增和递减。

【讨论】:

  • 节点应该有一个Add() 方法,否则你怎么下树?
  • 感谢@TimC,您对二叉树是正确的,但对于不平衡或非二叉树则不然。 IE。您不会将文件夹添加到位于“c:\”的“我的文档”文件夹中。
  • 那个 Add 方法不应该是公开的。树需要保护节点——它们是树的实现细节,而不是外界应该知道的东西。有几种方法可以保护该方法,但最重要的是,使用您的树的消费者永远不能直接在节点上调用 Add。树本身可能,但没有其他人。
  • @TimCopenhaver 我有兴趣查看示例实现。当前的实现和示例允许设置节点的父属性。有效地添加一个节点。您的前提表明,父母活动的所有移动、复制、删除和设置也将受到保护。
  • @Spevy 在这方面你可能是对的——当我谈到我见过的实现时,我的意思是野外解决方案,不一定是研究定义。您会注意到 DOM 和 MS XML 不提供任何结构函数(不存在计数等)。它们只是松散的节点集合。在您的情况下,您需要更强大的管理模式,更接近 BST 的工作方式。我之前已经写过好几次了,但我不确定是否有一个好的“标准”示例。
【解决方案3】:

您的 Node 类可以记录它有多少子节点,每次添加或删除节点时都会更新该节点。然后要获得根节点(或任何节点,就此而言)的计数,您只需将其所有子节点的计数相加即可。

但是为了简单起见,为什么不按照 D Stanley 的建议,递归地实现 Count 呢?

【讨论】:

  • @gilfish。谢谢我考虑过这种方法。我仍然必须遍历每个孩子才能找到孩子的孩子的孩子......你明白了。仍在穿过树。
  • 如果每个节点都缓存了它拥有的子节点数量,您就不必遍历每个子节点。当然,每次更改节点的子集合时,都必须更新缓存的计数,但是您只需查看第一级子节点即可获取计数。
  • @gilfish 如果我理解你的建议如下。将每个节点视为根节点,具有所有后代的计数值。如果我添加一个孩子说向下 20 级,我将不得不继续保持这些计数。
  • @Spevy 啊,我看到了我的错误。是的,我的解决方案将要求每个子节点都有一个指向其父节点的指针,然后您必须将更改一直传播到根节点。
  • 您的解决方案没有错。这与我上面考虑的设计思路一致,我只是觉得有些东西我忽略了。
【解决方案4】:

感谢大家的 cmets。我并不是真的想邀请辩论,只是想看看是否有人有样本,似乎没有。

我认为答案是没有好的样品可用,我需要自己完成这项工作。

我给你们每个人一个 +1,因为你们都对我的结论做出了贡献。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 2020-08-24
    • 2023-03-28
    • 2013-04-30
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    相关资源
    最近更新 更多