【问题标题】:C# tree node class designC#树节点类设计
【发布时间】:2016-02-16 14:45:39
【问题描述】:

我正在寻找一些关于如何组织分层树节点类的建议。

我有一个分层树,其中包含一些与树相关的成员,例如ParentChildrenAddNode()RemoveNode() 等。每个节点也使用特定于应用程序的数据。在阅读了大量文章后,我最终得出了两种可能的设计:

将树相关的成员与单个树节点类中的节点值成员结合起来:

public class TreeNodeClass {
    // tree-specific members
    public TreeNodeClass Parent { get; set; }
    public IList<TreeNodeClass> Children { get; set; }
    public void AddNode() { }
    public void RemoveNode() { }
    public IEnumerable<TreeNodeClass> Traverse() { }
    <...>
    // value-specific members
    public Type1 ValueSpecificProperty1 { get; set; }
    <...>
    public TypeN ValueSpecificPropertyN { get; set; }
    public void Method1() { }
    <...>
    public void MethodN() { }
}

在不同的类中拆分树节点和节点值:

1) 只包含与树相关的成员的树节点类;

2) 仅包含特定于值的成员的节点值类,并通过节点对象中的Value 成员引用此对象。

public class TreeNodeClass {
    public TreeNodeClass Parent { get; set; }
    public IList<TreeNodeClass> Children { get; set; }
    public TreeNodeValue Value { get; set; }
    public void AddNode() { }
    public void RemoveNode() { }
    public IEnumerable<TreeNodeClass> Traverse() { }
    <...>
}
public class TreeNodeValue {
    public Type1 ValueSpecificProperty1 { get; set; }
    <...>
    public TypeN ValueSpecificPropertyN { get; set; }
    public void Method1() { }
    <...>
    public void MethodN() { }
}

我的具体场景的一些细节:

  1. 节点值类应该有大约15个轻量级属性(它们是intbyteboolstring类型)和5-10个方法。
  2. 到目前为止,节点值不应该与其树节点对话,因此不需要节点值交叉引用。但是,树节点对象将与节点值对话(通过第二个设计中的Value 属性)。

我敢打赌,这两种情况都是有效的(因为它们在许多文章中被广泛使用),所以问题是:

  1. 是否首选这些设计?
  2. 如果不是,那么在选择之前我应该​​考虑哪些因素?

【问题讨论】:

  • 两种方法之间几乎没有什么不同。当节点值包含多个项目时,应使用第二种方法。不知道为什么你的 TreeNodeClass 不继承 Net 库 TreeNode 类。
  • 因为:1) 我必须重写 AddRemoveInsert 方法。为了修改树,我必须执行很多事情(它们是特定于应用程序的)。 2) 这是一个框架库,可以在有和没有 GUI 的应用程序中使用。此外,可能还有基于 WinForms 或 WPF(或其他)的 GUI。他们有不同的TreeNode 类。
  • 问题仍然是您的节点是单个值(第一个设计)还是多个值(第二个设计)?看起来您的场景是多个项目(15 个轻量级属性),这意味着您需要第二个设计。现在你需要一个特殊的 Add、Remove、Insert 方法来支持你的多个项目吗?
  • Add, Remove, Insert 方法用于管理树本身(添加、删除、插入节点),而不是值。问题不在于它们:我应该将树节点与节点值(这是一堆属性和方法)分开,还是将所有内容组合在同一个类中。
  • 知道Child 的复数形式是Children,您可能会感激不尽。

标签: c# tree


【解决方案1】:

我会把关注点分开。树的关注点是在修改时维护​​树的不变量。每个节点中数据的关注点是,不管它关注的是什么。

我要做的是创建一个通用容器类型Tree&lt;T&gt; 并让树对它的值一无所知,而这些值对它们所是的树一无所知在。

现在,在某些情况下,树必须了解一些值。例如,假设您正在构建一个权重平衡的二叉树,而不是您在此处构建的 n 叉树。权重平衡二叉树必须能够查询节点以找出它们有多“重”才能产生可​​接受的平衡。有几种方法可以做到这一点。一种方法是要求T 实现一些IWeight 接口。另一种方法是要求树的创建者提供一个Func&lt;T, double&gt; 代表,它可以产生T 的权重。无论哪种方式,树只知道它所需要的关于节点的信息,以便完成它的工作:维护树的不变量。

【讨论】:

  • 我的树不是二叉树,它可能在单个节点下有 0..MAX 个子元素。关于Tree&lt;T&gt;,你的意思是这样的:codeproject.com/Articles/679660/WPF-Tree-Data-Structure
  • @CryptoGuy:我知道您正在构建一个 n 叉树。我的加权树示例是为了表明在某些情况下,树不变量依赖于关于节点的事实;它们不一定是独立的。我的观点是,如果存在依赖项,您应该使依赖项尽可能小,并以特定方式捕获,例如接口或委托。
  • @CryptoGuy:就链接页面中的树而言,我已经阅读了第一行代码,但我已经不喜欢它了。无需使用 C# 风格的奇怪重复模板模式来制作树形数据结构。
  • 如果我在我引用的链接中实现类似的东西可以吗?
  • @CryptoGuy:是的,绝对是。链接文章中的想法非常好;我不同意一些设计决定,但基本想法是合理的。我将从比那里描述的树更简单且与 WPF 联系更少的东西开始。
猜你喜欢
  • 1970-01-01
  • 2013-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-26
  • 1970-01-01
  • 2013-02-12
  • 1970-01-01
相关资源
最近更新 更多