簡體   English   中英

C#中的這個樹實現有什么問題?

[英]What's wrong with this tree implementation in C#?

我目前正在嘗試在C#中實現一個非常簡單的樹/節點類,其中節點有一個對象作為數據,並且它們可以有零到多個子節點。 我目前遇到兩個問題:

  1. 出於某種原因,打印出對象最終會打印對象的TYPE,而不是每個不是根節點的toString()。
  2. 我似乎無法正確打印我的樹的多個分支,並且無法找到問題,是否是我的打印方法的問題或我將節點添加到節點的方式。

我的Node類如下。

namespace Tree
{
    class Node
    {
        public object data;
        private LinkedList<Node> children;

        public Node(object data)
        {
            this.data = data;
            children = new LinkedList<Node>();
        }

        public void Add(params object[] objects)
        {
            foreach (object obj in objects)
            {
                children.AddLast(new Node(obj));
            }
        }

        public int Count()
        {
            int count = 1;

            foreach (Node n in children)
            {
                count += n.Count();
            }

            return count;
        }

        public void Print(int depth)
        {
            string s = new string('\t',depth);
            s += data;
            Console.WriteLine(s);
            depth++;

            foreach (Node n in children)
            {
                n.Print(depth);
            }
        }
    }
}

為了測試,我正在創建一個帶有三個孩子的根的樹,然后這三個孩子中的每一個都有三個孩子,如下所示。

Node core = new Node("root");

Node o1 = new Node("1");
Node o2 = new Node("2");
Node o3 = new Node("3");

o1.Add(new Node("11"), new Node("12"), new Node("13"));
o2.Add(new Node("21"), new Node("22"), new Node("23"));
o3.Add(new Node("31"), new Node("32"), new Node("33"));
core.Add(o1, o2, o3);

Console.WriteLine(core.Count());
core.Print(0);

預期的產出當然是:

13
root
 1
  11
  12
  13
 2
  21
  22
  23
 3
  31
  32
  33

不幸的是我得到:

4
root
    Tree.Node
    Tree.Node
    Tree.Node

這是我第一次在C#中進行遞歸,所以也許有一些我想念的簡單。 如果是這種情況,我寧願解釋問題而不是代碼中給出的解決方案。 謝謝。

快速解決:

public void Add(params Node[] objects)
{
    foreach (Node obj in objects)
    {
        children.AddLast(obj);
    }
}

如果您的Add方法應該添加子節點,那么首先應該為objects參數使用相應的類型。 其次,您應該刪除對Node其他對象轉換,因為您已經傳遞了Node類型參數。

問題出在您的Add()方法上。 目前,它被實現為接收對象並添加具有這些對象的節點。 但是您正在使用它來添加子節點。 您需要兩種不同的方法:

public void AddObjects(params object[] objects)
{
    foreach (object obj in objects)
    {
        children.AddLast(new Node(obj));
    }
}

public void AddChildNodes(params Node[] nodes)
{
    foreach (Node node in nodes)
    {
        children.AddLast(node);
    }
}

然后在您設置樹結構的地方,使用AddChildNodes()而不是Add()

這就是設置代碼的外觀:

Node core = new Node("root");

Node o1 = new Node("1");
Node o2 = new Node("2");
Node o3 = new Node("3");

o1.AddObjects("11", "12", "13");
o2.AddObjects("21", "22", "23");
o3.AddObjects("31", "32", "33");
core.AddChildNodes(o1, o2, o3);

Console.WriteLine(core.Count());
core.Print(0);

除了現有的答案,不要用+=字符串:

s += data;

采用

s = String.Concat(s, data.ToString()); 

代替。

data真的需要是對象類型嗎? 如果不了解整個系統,這只是一個猜測,但是有一個通用的Node類是可行的:

class Node<T> 
{
  public T data;
  ...
  public void AddChild(Node<T> childNode) ...
  public void AddChilds(IEnumerable<Node<T>> childNode) ...
}


Node<String> root = new Node<String>("root");
root.AddChild(new Node<String>("FirstBelowRoot");
public Node(object data)
{
    this.data = data;
    children = new LinkedList<Node>();
}

在這里,當您執行Add(new Node("11"))之類的操作時,您將此節點的data初始化為Node類型的對象。 實質上,您構建的節點現在包含另一個節點作為數據,而不是您最初預期的“11”。

不要將object用於任何事情,作為C#學習的一部分,沒有理由這樣做,它只會咬你,就像你在這里發現的那樣。 使用泛型或標記的聯合類型來獲取可包含不同類型數據的節點。

了解泛型,然后重新審視您的樹實現,這是我的建議。

這不是你問題的直接答案,而是關於如何構建你的課程的更多建議。

嘗試這個:

public class Node<T> : LinkedList<Node<T>>
{
    public T Data { get; set; }

    public Node(T data)
    {
        this.Data = data;
    }
}

而已。 好吧,至少這是你的核心代碼。 您需要這組擴展方法來使用它:

public static class NodeEx
{
    public static void Add<T>(this Node<T> tree, Node<T> child)
    {
        tree.AddLast(child);
    }

    public static int Count<T>(this Node<T> tree)
    {
        int count = 1;
        foreach (Node<T> n in tree)
        {
            count += n.Count();
        }
        return count;
    }

    public static void Print<T>(this Node<T> tree, int depth)
    {
        Console.WriteLine(new string('\t', depth) + tree.Data);
        foreach (Node<T> n in tree)
        {
            n.Print(depth + 1);
        }
    }
}

現在使用void Add<T>(this Node<T> tree, Node<T> child)擴展方法,您可以編寫以下代碼:

Node<string> core = new Node<string>("root")
{
    new Node<string>("1")
    {
        new Node<string>("11"),
        new Node<string>("12"),
        new Node<string>("13")
    },
    new Node<string>("2")
    {
        new Node<string>("21"),
        new Node<string>("22"),
        new Node<string>("23")
    },
    new Node<string>("3")
    {
        new Node<string>("31"),
        new Node<string>("32"),
        new Node<string>("33")
    },
};

int Count<T>(this Node<T> tree)void Print<T>(this Node<T> tree, int depth)按預期工作。 這段代碼:

Console.WriteLine(core.Count());
core.Print(0);

...生產:

13
root
  1
    11
    12
    13
  2
    21
    22
    23
  3
    31
    32
33

現在,最大的優點是針對LinkedList<T>對象的所有LinkedList<T>方法都適用於Node<T>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM