我有一个对象集合(List<Element>),如下所述:
class Element
{
string Name;
string Value;
ICollection<Element> ChildCollection;
IDictionary<string, string> Attributes;
}我基于读入的一些XML构建了一个Element对象的List<Element>集合,我对此非常满意。如何实现对这些元素的搜索目前对我来说并不困惑,但我想知道是否有更好的解决方案。
该集合的结构如下所示:
- Element (A)
- Element (A1)
- Element (A1.1)
- Element (A2)
- Element (B)
- Element (B1)
- Element (B1.1)
- Element (B1.2)
- Element (C)
- Element (C1)
- Element (C2)
- Element (C3)目前,我正在使用递归在每个顶级(A,B,C) Element的Attributes字典中搜索特定的KeyValuePair。如果我在顶层Element中找不到它,我就开始搜索它的ChildElement集合(1,1.1,2,2.1,n等)。以同样的方式。
我好奇的是,是否有更好的方法在这些对象上实现搜索,或者在这种情况下递归是更好的答案,如果我应该像现在一样实现搜索,top -> child -> child ->等,还是应该以其他方式搜索,比如先搜索所有顶级?
我可以使用TPL并行搜索每个顶级(A、B、C)吗?
发布于 2013-07-13 21:25:39
递归是实现按深度优先顺序访问元素的树搜索的一种方式。您可以使用循环而不是递归来实现相同的算法,方法是使用堆栈数据结构来存储需要访问的树的节点。
如果对队列而不是堆栈使用相同的算法,则搜索将以呼吸优先的顺序进行。
在这两种情况下,一般算法如下所示:
var nodes = ... // some collection of nodes
nodes.Add(root);
while (nodes.Count != 0) {
var current = nodes.Remove ... // Take the current node from the collection.
foreach (var child in current.ChildCollection) {
nodes.Add(child);
}
// Process the current node
if (current.Attributes ...) {
...
}
}请注意,该算法不是递归的:它使用显式的nodes集合来保存搜索的当前状态,而递归实现则使用调用堆栈来实现相同的目的。如果nodes是Stack<Element>,则搜索在depth-first order中进行;如果nodes是Queue<Element>,则搜索在breadth-first order中进行。
发布于 2013-07-13 21:25:27
您可以重用专为以不同方式遍历而设计的现有组件,例如NETFx IEnumerable.Traverse Extension Method。它允许您首先选择深度或广度。它允许您首先遍历可枚举树,深度或广度。
获取平面化的目录枚举表的示例:
IEnumerable<DirectoryInfo> directories = ... ;
IEnumerable<DirectoryInfo> allDirsFlattened = directories.Traverse(TraverseKind.BreadthFirst, dir => dir.EnumerateDirectories());
foreach (DirectoryInfo directoryInfo in allDirsFlattened)
{
...
}对于BreadhFirst,它在内部使用Queue<>,对于DepthFirst,它在内部使用Stack<>。
它不是并行遍历节点,除非遍历是需要资源的,否则在这个级别上使用并行化是不合适的。但这取决于上下文。
发布于 2013-07-13 21:33:08
我从某个地方抓取了这个比特,它不是我的,但我无法提供它的链接。这个类为递归搜索展平了一个树形视图,看起来它也应该为你做同样的事情。
public static class SOExtension
{
public static IEnumerable<TreeNode> FlattenTree(this TreeView tv)
{
return FlattenTree(tv.Nodes);
}
public static IEnumerable<TreeNode> FlattenTree(this TreeNodeCollection coll)
{
return coll.Cast<TreeNode>()
.Concat(coll.Cast<TreeNode>()
.SelectMany(x => FlattenTree(x.Nodes)));
}
}我找到了我得到这个的链接--它非常容易使用。看一看。Is there a method for searching for TreeNode.Text field in TreeView.Nodes collection?
https://stackoverflow.com/questions/17630557
复制相似问题