C#中这个树实现有什么问题?

时间:2016-01-30 13:54:57

标签: c# tree nodes

我目前正在尝试在C#中实现一个非常简单的树/节点类,其中节点有一个对象作为数据,并且它们可以有零到多个子节点。我现在遇到两个问题:

  1. 由于某种原因,打印出对象最终会打印TYPE 而不是它的每个节点的toString()而不是它 根。
  2. 我似乎无法正确打印出树的多个分支, 并且无法找到问题,无论是我的打印问题 方法或我将子节点添加到节点的方式。
  3. 我的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#中进行递归,所以也许我有一些简单的错过。如果是这种情况,我宁愿解释问题而不是代码中给出的解决方案。谢谢。

5 个答案:

答案 0 :(得分:2)

快速修复:

yara.h

如果您的go-yara.a方法应该添加子节点,那么首先应该使用pkg参数的相应类型。其次,您应该删除其他对象转换为public void Add(params Node[] objects) { foreach (Node obj in objects) { children.AddLast(obj); } } ,因为您已经传递了Add类型参数。

答案 1 :(得分:1)

问题在于你的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);

答案 2 :(得分: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");

答案 3 :(得分:0)

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

当您执行data之类的操作时,您可以将此节点的Node初始化为Add(new Node("11"))类型的对象。从本质上讲,您构建的节点现在包含另一个节点作为数据,而不是您最初打算的#34; 11&#34 ;.

不要使用object做任何事情,作为C#学习的一部分,没有理由这样做,而且只能在你发现的时候咬你。使用泛型或标记的联合类型来获取可包含不同类型数据的节点。

了解泛型,然后重新审视树的实现,这是我的建议。

答案 4 :(得分:0)

这不是您问题的直接答案,更多是关于如何构建课程的建议。

试试这个:

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)&amp; 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>对象的所有常用方法适用于Node<T>