c# - 遍历树结构

标签 c# tree

我试图了解如何遍历树数据结构,但在执行此操作时遇到问题,特别是当我尝试使用 IEnumerable 时。我希望树作为字典,这样我就可以通过节点的字符串名称来引用节点。该树将保存不同的类对象,但这些对象都实现一个接口(interface) IMyInterface ,树的类型将是 IMyInterface界面。

我有树:

internal class Tree<T>
{
    private TreeNode<T> root;

    internal Tree(T value)
    {
        if (value == null)
        {
            throw new ArgumentNullException(
                "Cannot use a null value to construct a tree.");
        }

        this.root = new TreeNode<T>(value);
    }

    internal Tree(T value, params Tree<T>[] children) : this(value)
    {
        foreach (Tree<T> child in children)
        {
            this.root.AddChild(child.root);
        }
    }

    internal TreeNode<T> Root
    {
        get { return this.root; }
    }

    private void PrintDFS(TreeNode<T> root, int spaces)
    {
        if (spaces < 0)
        {
            throw new ArgumentOutOfRangeException(
                "The number of spaces used to represent the parent-child relation in a tree must be greater than or equal to zero.");
        }

        if (this.root == null)
        {
            return;
        }

        StringBuilder sb = new StringBuilder();
        sb.Append(' ', spaces);
        sb.Append(root.Value);

        TreeNode<T> child = null;

        foreach (Tree<T> child in this.root)     // <--- this generates an error
        {
            PrintDFS(child, spaces);
        }
    }

    // Traverses and prints the tree in
    // Depth-First Search (DFS) manner
    internal void TraverseDFS()
    {
        this.PrintDFS(this.root, 0);
    }
}

我的节点类是:

internal class TreeNode<T> : IEnumerable<TreeNode<T>>
{
    private T value;
    private bool hasParent;

    private readonly Dictionary<string, TreeNode<T>> children = new Dictionary<string, TreeNode<T>>();

    internal TreeNode(T value)
    {
        if (value == null)
        {
            throw new ArgumentNullException(
                "Cannot insert null values for a tree node!");
        }

        this.value = value;
        this.children = new Dictionary<string, TreeNode<T>>();      // dictionary that holds the children of each node
    }

    internal T Value
    {
        get { return this.value; }
        set { this.value = value; }
    }

    internal int ChildrenCount
    {
        get
        {
            return this.children.Count;
        }
    }

    internal void AddChild(TreeNode<T> child)
    {
        if (child == null)
        {
            throw new ArgumentNullException(
                "Cannot insert null value as child node.");
        }

        if (child.hasParent)
        {
            throw new ArgumentException(
                "The child node already has a parent.");
        }

        child.hasParent = true;
        this.children.Add(child.ToString(), child);
    }

    internal TreeNode<T> GetChild(string nodeName)
    {
        return this.children[nodeName];
    }

    internal IEnumerator<TreeNode<T>> GetEnumerator()
    {
        return this.children.Values.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    IEnumerator<TreeNode<T>> IEnumerable<TreeNode<T>>.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

问题似乎是代码:

foreach (Tree<T> child in this.root)     // <--- this generates an error
{
    PrintDFS(child, spaces);
}

(来自 Tree 类的代码片段)任何建议将不胜感激。

编辑

我收到错误消息:

错误 669 无法在此作用域中声明名为“child”的局部变量,因为它会给“child”赋予不同的含义,而“child”已在“父或当前”作用域中用于表示其他内容。

错误 672 无法转换类型 TreeNode<T>Tree<T>

以及警告消息:

警告 668 TreeNode<T>不实现“集合”模式。 TreeNode<T>.GetEnumerator()要么是静态的,要么是非公开的。

最佳答案

问题#1

Error 669 A local variable named 'child' cannot be declared in this scope because it would give a different meaning to 'child', which is already used in a 'parent or current' scope to denote something else.

TreeNode<T> child = null;

foreach (Tree<T> child in this.root)     // <--- this generates an error
{
     PrintDFS(child, spaces);
}

您已经拥有 child多变的。您需要以不同的方式命名它们。这个错误是非常不言自明的。

对于这种情况,只需删除 child从上面foreach因为它在那里没用。

foreach (var child in this.root) 
{
     PrintDFS(child, spaces);
}

我想你想要TreeNode<T> ,但不确定 root 实际应该返回什么.

问题#2

Error 672 Cannot convert type TreeNode to Tree

如果你应该循环 TreeNode<T> ,不是Tree<T>如错误所述。只需使用 var除非您实际上尝试迭代树而不是节点。

问题 #3

Warning 668 TreeNode does not implement the 'collection' pattern. TreeNode.GetEnumerator() is either static or not public.

它需要公开。 Internal 不会削减它,因为它需要遵守 IEnumerable 契约。看来您已经通过显式实现解决了这个问题。

关于c# - 遍历树结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27051227/

相关文章:

python - 构建系统发育树

c# - 我的线性算法的缺陷在哪里

c# - WPF:如何处理模型中的事件以动态更新 MVVM 中的 xaml

c# - 在 C# 中实现选择类型

c# - EF5 删除实体时出现问题。它以前有效...我哪里出错了?

c++ - BST 插入 C++ 帮助

node.js - 如何覆盖 Windows 树命令?

c# - Topshelf 服务(充当 TCP 服务器)与自托管 OWIN WebAPI 之间的通信

c# - CloudConfigurationManager 不会覆盖外部文件中的设置

java - 将 SWT 树中的项目在父级之间移动