亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在C#中定義一個可繼承的樹類來構建由不同類類型組成的樹狀數據結構?

如何在C#中定義一個可繼承的樹類來構建由不同類類型組成的樹狀數據結構?

C#
青春有我 2021-11-21 10:59:21
我一直在閱讀這個主題一段時間,但我只是不太了解 C# 語法。希望這對您來說很清楚,并且您愿意幫助我。我發現的例子是相同類型或類的樹結構,這不是我在這里需要的。簡而言之,我希望能夠定義任意類,例如下面的 NodeClassA、NodeClassB、NodeClassC,并且能夠將任意數量的這些相互附加以形成如下所示的任意樹數據結構。每個節點都應該能夠訪問其父節點。任何人都可以幫助正確定義下面的 MyTreeClass 嗎?NodeClassB__NodeClassC__NodeClassA____NodeClassB____NodeClassB____NodeClassA__NodeClassA____NodeClassC__NodeClassB__NodeClassCclass MyTreeClass{    public void AddChild(T NodeClassX) { }    public T GetChild() { }}class NodeClassA:MyTreeClass{    public void foo(int a) { }}class NodeClassB : MyTreeClass{    public void foo(int b) { }}class NodeClassC : MyTreeClass{    public void foo(int c) { }}
查看完整描述

3 回答

?
RISEBY

TA貢獻1856條經驗 獲得超5個贊

這在嚴格的類型安全方式中是不可能的,因為類型安全是在編譯時確保的,這需要靜態聲明類型。但是樹是在運行時動態構建的,具有不同的節點類型。


要走的路是擁有一個可以是通用的靜態節點數據類型。可以從給定的基本數據類型導出不同類型的數據。使用多態來處理它們。即使用具有不同實現的相同方法集。


public class TreeNode<T>

{

    public T Data { get; set; }


    private List<TreeNode<T>> _children = new List<TreeNode<T>>();

    public IEnumerable<TreeNode<T>> Children => _children;


    public TreeNode<T> AddChild(T data)

    {

        var node = new TreeNode<T> { Data = data };

        _children.Add(node);

        return node;

    }


    public void VisitPreOrder(Action<T, int> action, int level)

    {

        action(Data, level);

        foreach (TreeNode<T> node in Children) {

            node.VisitPreOrder(action, level + 1);

        }

    }

}


public class Tree<T>

{

    public TreeNode<T> Root { get; } = new TreeNode<T>();


    public void VisitPreOrder(Action<T, int> action)

    {

        Root.VisitPreOrder(action, 0);

    }

}

現在您可以擁有與樹完全無關的數據類:


public class A

{

    public int Index { get; set; }


    public virtual void PrintLine()

    {

        Console.WriteLine($"A {Index}");

    }

}


public class B : A

{

    public override void PrintLine()

    {

        Console.WriteLine($"B {Index}");

    }

}


public class C : B

{

    public override void PrintLine()

    {

        Console.WriteLine($"C {Index}");

    }

}

從您的示例創建樹結構


TreeNode<A> node;


var tree = new Tree<A>();

tree.Root.Data = new B { Index = 0 };            // NodeClassB

tree.Root.AddChild(new C { Index = 1 });         // __NodeClassC

node = tree.Root.AddChild(new A { Index = 2 });  // __NodeClassA

node.AddChild(new B { Index = 3 });              // ____NodeClassB

node.AddChild(new B { Index = 4 });              // ____NodeClassB

node.AddChild(new A { Index = 5 });              // ____NodeClassA

node = tree.Root.AddChild(new A { Index = 6 });  // __NodeClassA

node.AddChild(new C { Index = 7 });              // ____NodeClassC

tree.Root.AddChild(new B { Index = 8 });         // __NodeClassB

tree.Root.AddChild(new C { Index = 9 });         // __NodeClassC 

因為每個數據類型(基類型或派生類型)都做適合其類型的事情,所以您不需要知道它的確切類型。這稱為多態。這將打印樹結構:


tree.VisitPreOrder((item, level) => {

    Console.Write(new string('_', 4 * level));

    item.PrintLine();

});

B 0

____C 1

____A 2 ____B

3 ____B

4

________A 5

____A 6

________C 7

____B 8

____C 9


請注意,T在聲明Tree<T>andTreeNode<T>類時,您不需要知道具體的數據類型,因為它T是通用的。你也可以聲明


var stringTree = new Tree<string>();

var intTree = new Tree<int>();


查看完整回答
反對 回復 2021-11-21
?
紅顏莎娜

TA貢獻1842條經驗 獲得超13個贊

您可能正在尋找復合模式,這是一種對樹結構建模的常用方法,例如一個文件系統,其中您有一個葉子(文件)和容器(文件夾),而容器可以包含其他容器或葉子本身。


在您的情況下,至少到目前為止您描述的方式要簡單一些,因為這些節點之間沒有行為差異。所以對于你的結構,節點實際上可以是淺的,你只需要在你的基類中實現組合。這樣,您就沒有葉子,而只有(不同的)容器。


public abstract class BaseNode

{

    public IList<BaseNode> Children

    { get; } = new List<BaseNode>();

}


public class NodeClassA : BaseNode { }

public class NodeClassB : BaseNode { }

public class NodeClassC : BaseNode { }

然后你就可以構建你的結構了。


查看完整回答
反對 回復 2021-11-21
?
慕娘9325324

TA貢獻1783條經驗 獲得超4個贊

只需讓您的任意類繼承或組合某種類型的集合即可。例如,您的任意類都可以是列表。增強將是 add 方法設置子級的父級并且父級是一個屬性。


查看完整回答
反對 回復 2021-11-21
  • 3 回答
  • 0 關注
  • 228 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號