我试图了解如何遍历树数据结构,但在执行此操作时遇到问题,特别是当我尝试使用 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/