这是此帖的后续帖子:Recursively search nested lists
我一直在尝试修改导致我返回子项所在的父项的代码,但由于某种原因,这个函数的递归方面并没有很好地流入我的大脑。
在一个完美的世界中,我希望能够指定最多返回多少个父节点,但即使只是直接的节点也会很棒。
public static AccessibleTreeItem Find(AccessibleTreeItem node, string name)
{
if (node == null)
return null;
if (node.name == name)
return node;
foreach (var child in node.children)
{
var found = Find(child, name);
if (found != null)
return found;
}
return null;
}
感谢所有人花时间看一看。
编辑:所以,例如,我希望能够调用Find(node,name,parentIndex)或类似的东西来传递一个值,该值表示返回的项目可以找到父级别的数量在。
编辑2:为了澄清,我希望能够告诉函数找到一个特定的名称和一个parentIndex。该函数将定位要搜索的节点,然后遍历“树”指定的级别数,最后返回该对象。
所以,如果我们打电话
Find(node, "Test", 2)
正在搜索的值位于:
node.children[0].children[3].children[2].children[1]
然后该函数应该返回位于:
的对象 node.children[0].children[3]
答案 0 :(得分:1)
啊哈...所以尝试传递 byref 一个名为“ancestorCount”的正(整数)整数(父亲为1,祖父母为2,祖父等为3等)。 ..如果找到返回true(非null)并且ancestorCount == 0返回此值,则在返回找到的子项之前减去ancestorCount ...
这对你有意义吗?我将在大约10分钟内编辑这篇文章,将其放入psuedocode(至少)。
干杯。基思。
编辑:至少提供排序代码。
这不是编译的,很容易被测试......因此我完全不确定我的条件是否正确......正如Ben指出的那样,我可能会完全屁股;-)这种情况我通常需要调试一段时间才能正确...但我确实认为“我非常接近”,核心思想就在那里......我会把微调调整到实施者......你; - )
public static Node Find(Node node, string targetName, ref int ancenstorCount) {
if ( node == null )
return null;
if ( ancenstorCount == 0 ) // we've already found the right level to return
return node;
if ( node.name == targetName )
return node;
foreach ( Node child in node.Children ) {
var found = Find(child, targetName);
if ( found != null ) {
if ( ancenstorCount == 0 )
return found;
--ancenstorCount;
return node; // return any non-null
}
}
return null;
}
...但是我可以看到我现在必须实现Node,只是为了满足我对我的算法正确性的好奇心。叹息。
干杯。基思。
<强> EDIT2:强>
嗯,这对我有用......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tree
{
class Node {
private List<Node> _kids = new List<Node>();
public string Name { get; set; }
public List<Node> Children { get { return _kids; } }
public void Add(Node child) { _kids.Add(child); }
public override string ToString() { return Name; }
}
class Program
{
Node _root;
static void Main(string[] args) {
new Program().Run();
Console.Write("Press any key ...");
Console.ReadKey();
}
Program() {
_root = GenerateTree();
}
static Node GenerateTree()
{
// Gen0
Node root = new Node() { Name = "Great-grandpa Jimmy Joe Jim-Bob John Keith Luke Duke" };
// Add Gen1 to Gen0
root.Add(new Node() { Name = "GrandUncle Joe Duke" });
Node grandDad = new Node() { Name = "Granddad Jimmy Duke" };
root.Add(grandDad);
// Add Gen2 to Gen1
grandDad.Add(new Node() { Name = "Uncle Jim" });
grandDad.Add(new Node() { Name = "Uncle Bob" });
Node dad = new Node() { Name = "Dad John" };
grandDad.Add(dad);
// Add Gen3 to Gen2
dad.Add(new Node() { Name = "Brother Luke" });
dad.Add(new Node() { Name = "Keith" });
return root;
}
void Run() {
Console.WriteLine("My Great-granddad is: " + Find("Keith", 3));
Console.WriteLine("My granddad is: " + Find("Keith", 2));
Console.WriteLine("My dad is: " + Find("Keith", 1));
Console.WriteLine();
Console.WriteLine("Brother Luke's Dad is: " + Find("Brother Luke", 1));
Console.WriteLine("Uncle Bob's dad is: " + Find("Uncle Bob", 1));
Console.WriteLine("Uncle Jim's granddad is: " + Find("Uncle Jim", 2));
Console.WriteLine();
Console.WriteLine("Lunil's mom is: " + Find("Lunil", 1));
Console.WriteLine();
}
string Find(string targetName, int anticedentLevel) {
Node n = Find(_root, targetName, ref anticedentLevel);
return n!=null ? n.ToString() : "#NOT_FOUND#";
}
private static Node Find(Node node, string targetName, ref int ancenstorCount) {
if ( node == null )
return null;
if ( ancenstorCount == 0 ) // we've already found the right level to return
return node;
if ( node.Name == targetName )
return node;
foreach ( Node child in node.Children ) {
var found = Find(child, targetName, ref ancenstorCount);
if ( found != null ) {
if ( ancenstorCount == 0 )
return found;
--ancenstorCount;
return node; // return any non-null
}
}
return null;
}
}
}
输出
My Great-granddad is: Great-grandpa Jimmy Joe Jim-Bob John Keith Luke Duke My granddad is: Granddad Jimmy Duke My dad is: Dad John Brother Luke's Dad is: Dad John Uncle Bob's dad is: Granddad Jimmy Duke Uncle Jim's granddad is: Great-grandpa Jimmy Joe Jim-Bob John Keith Luke Duke Lunil's mom is: #NOT_FOUND# Press any key ...
...虽然在现实世界中你可能“只是”在每个节点中使用父引用来实现它,只是因为它更简单......并且对其他事物很有用。
答案 1 :(得分:0)
我不知道“AccessibleTreeItem”是什么 - 但如果它有一个父属性,那么循环到node.Parent.Parent很容易。
例如:
public AccessibleTreeItem GetParent(AccessibleTreeItem node, int depth)
{
if(depth <= 1) // can't go higher than 1
{
return node.Parent;
}
else
{
return GetParent(node.Parent, depth-1);
}
}
那么从现有的递归开始,返回GetParent(节点,深度)而不是返回节点
但是,如果您没有父参考,那么您需要更具创造性。我看到corlettk正在研究这个例子,听起来他正在做我想做的事情,所以我会把它留给他。