2009-08-27 83 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. 
}