2009-08-27 86 views
2

我在处理这个特定问题的最佳方法方面遇到了棘手的时间,并且真的很想从专家社区获得一些指导!C#2.0包含多种类型的通用树

比方说,我有3个班

Branch 
Twig 
Leaf 

一个Branch可以包含其他Branch对象的集合,也可以包含Twig对象的集合和Leaf对象的集合。

A Twig可以包含其他Twig对象的集合,但也可以包含Leaf对象的集合。

A Leaf对象可以被视为基本组件,并且不包含任何其他对象的集合。

因此,可能的是钢结构

Branch    Branch     Branch 
|      |      | 
|_Branch    |_Twig     |_Leaf 
| |_etc...   | |_etc... 
|      | 
|_Twig    |_Leaf 
| |_etc... 
| 
|_Leaf 

枝条

Twig     Twig 
|      | 
|_Twig    |_Leaf 
| |_etc... 
| 
|_Leaf 

Leaf 

给定一个Branch,我想是能够询问任何后代BranchTwig,或Leaf对象和知道

  1. 每个派生对象有助于顶部对象的比率(该比率是上下文对于每种情况下的父母和孩子对象)。

  2. 如果特定类型的派生对象包含特定的属性值。例如,检查派生Leaf对象,看是否超过4有UnderSide属性值"Furry"

我也想能有选项

3.enumerate通过对象的后代水平一次是所有第一个孩子的有序列表,其次是所有第二个孩子等等(每个级别中的对象的顺序无关紧要)。

  1. 通过对象列举广度方面,即第一个孩子的有序列表,如果第一个孩子有孩子,那么第一个孩子的孩子,那么如果该对象有孩子,那么它是孩子。 ..then第二个孩子,等...

我首先想到的是用一个通用的树和接口多态性,但我在工作中出细节难度 - TwigLeaf对象有着一些共同的特性,但Branch对象是非常不同的。如果我只处理一种类型的对象,它将非常简单!这可以以类型安全的方式完成吗?

任何帮助将不胜感激。

回答

3

我会用接口来决定谁还能持有什么:

public interface IBranch { } 
public interface ITwig { } 

public class Branch : IBranch 
{ 
    List<IBranch> _Kids = new List<IBranch>(); 
    public List<IBranch> Kids 
    { 
     get { return _Kids; } 
    } 
} 

public class Twig : ITwig, IBranch 
{ 
    List<ITwig> _Kids; 
    public List<ITwig> Kids 
    { 
     get { return _Kids; } 
    } 
} 

public class Leaf : ITwig, IBranch 
{ 
} 

实现枚举并确保您在“枚举返回此”之前枚举子项。将IBranch中的所有常用功能放在一起,以及ITwig中的叶和枝之间的通用性会很好。

希望这有助于!

+0

这是最好的解决方案。但是,我认为在三个级别上使用“Root”,“Branch”和“Leaf”会比使用“Branch” ,“树枝”和“叶子”。 – 2009-09-02 15:11:36

1

他们确实都有着比房地产虽然没有他们,所以你可以在最起码让他们都实现了一些IRatio接口...

+0

的比率不是每个物件本身相当财产 - 的比例是包含对象,而不是对象本身的节点的属性 - 不有道理?让我知道,如果我的问题描述是误导性的,我会很乐意改变它 – 2009-08-27 09:53:26

+0

欲了解更多信息 - 儿童的比例是上下文相关的。以一个叶子对象为例。在db中,一个特定的叶子ID可能是一个以上不同树枝的孩子 - 叶子对树枝贡献的每个顺序中的比率可能不同 – 2009-08-27 09:58:18

+0

啊哈,我明白了,但是你有treenodes(即a包含分支,枝条或叶的数据结构)是否不能遍历包含的树数据结构,然后根据有效负载类型计算比率? – Colin 2009-08-27 10:15:03

1

这是我怎么可能会做它:

public interface INodeChild 
{ 
    public INodeParent Parent {get;set;} 
    //Any methods/properties common to ALL inheritors 
} 

public abstract class NodeParent : INodeChild 
{ 
    public INodeParent Parent {get; protected set;} 

    public IList<INodeChild> Children {get;set;} 
    // This is just breadth-wise since I'm more familiar with that. 
    public string ListChildren(int level) 
    { 
     StringBuilder sb = new StringBuilder(); 
     foreach(INodeChild item in Children) 
     { 
      sb.AppendLine(Enumerable.Repeat(" ", level)); 
      INodeParent itemParent = item as INodeParent; 
      if(itemParent != null) 
      { 
       itemParent.ListChildren(++level); 
      } 
     } 
     return sb.ToString(); 
    } 
    //Any methods/properties common to all parent inheritors (brach/twig/etc) 
} 

public class Brach : NodeParent 
{ 
    // Any branch only stuff goes here. 
} 

public class Twig : NodeParent 
{ 
    // Any twig only stuff goes here 
} 

public class Leaf : INodeChild 
{ 
    // Any leaf only stuff goes here. 
}