最近朋友提出的有趣问题:想象一下,你有一个List< NodeType>树中的所有节点。您将如何从行根节点向下遍历树,以便您找到具有特定值的第一个节点。所以说每个节点都有3个属性:它的名称/位置,它的父节点的身份,以及谁“拥有”节点。问题是你想在树中找到你所拥有的最高节点,无论它在哪个分支上。我理解基本逻辑,以找到第一组子项,查找父项设置为第一个节点的所有节点。但是你将如何递归搜索List<>节点找到你拥有的最高节点?
答案 0 :(得分:9)
您正在寻找广度优先搜索。它通常使用队列实现:
public Node FindFirstByBreadthFirst(this Node node, Predicate<Node> match)
{
var queue = new Queue<Node>();
queue.Enqueue(tree.RootNode);
while (queue.Count > 0)
{
// Take the next node from the front of the queue
var node = queue.Dequeue();
// Process the node 'node'
if (match(node))
return node;
// Add the node’s children to the back of the queue
foreach (var child in node.Children)
queue.Enqueue(child);
}
// None of the nodes matched the specified predicate.
return null;
}
答案 1 :(得分:2)
算法:
Put the root node in a queue.
Repeat
Take item from queue;
Matching? return Item
Add all children to the queue
Until Queue is empty
答案 2 :(得分:0)
更新:哈哈,哇,这是完全错误的,我刚刚意识到(因为它是不做你要求的)。没关系 - 看起来你已经得到了正确的答案,无论如何:)
我想我理解你的问题。如果我出错了,请告诉我。
你有一个NodeType
类看起来像这样:
class NodeType
{
public string Name { get; }
public NodeType Parent { get; }
public int OwnderId { get; }
}
第一项业务是编写一个带有NodeType
参数的函数,并且在给定一些NodeType
个对象的可枚举集合的情况下,以递归方式返回所有后代:
IEnumerable<NodeType> GetNodeChildren(NodeType node, IEnumerable<NodeType> nodes)
{
var children = nodes.Where(n => n.Parent == node);
if (children.Any())
{
foreach (NodeType child in children)
{
yield return child;
var grandchildren = GetNodeChildren(child);
foreach (NodeType grandchild in grandchildren)
{
yield return grandchild;
}
}
}
}
接下来:编写一个带有NodeType
对象的函数,并找到具有指定OwnerId
的最高后代。这真的是一个非常简单的操作,所以我甚至不会定义一个合适的函数;我只会使用lambda:
Func<NodeType, int, NodeType> findHighestDescendent = (node, id) => {
return GetNodeChildren(node).FirstOrDefault(child => child.OwnerId == id);
};
现在,对于任何给定的Id值,找到最高匹配NodeType
非常简单:
int id = 10; // just for example
NodeType highestOwnedNode = nodes
.Select(n => findHighestDescendent(n, id))
.FirstOrDefault(n => (n != null));
答案 3 :(得分:-4)
public static Control FindChildControlByDepth(this Control Page, string ControlID, int depth)
{
if (depth > 10)
throw new ArgumentException("Cannot search beyond a depth of 10", "depth");
foreach (Control c in Page.Controls)
{
if (c.ID == ControlID)
return c;
if (depth > 0)
{
foreach (Control c1 in c.Controls)
{
if (c1.ID == ControlID)
return c1;
if (depth > 1)
{
foreach (Control c2 in c1.Controls)
{
if (c2.ID == ControlID)
return c2;
if (depth > 2)
{
foreach (Control c3 in c2.Controls)
{
if (c3.ID == ControlID)
return c3;
if (depth > 3)
{
foreach (Control c4 in c3.Controls)
{
if (c4.ID == ControlID)
return c4;
if (depth > 4)
{
foreach (Control c5 in c4.Controls)
{
if (c5.ID == ControlID)
return c5;
if (depth > 5)
{
foreach (Control c6 in c5.Controls)
{
if (c6.ID == ControlID)
return c6;
if (depth > 6)
{
foreach (Control c7 in c6.Controls)
{
if (c7.ID == ControlID)
return c7;
if (depth > 8)
{
foreach (Control c8 in c7.Controls)
{
if (c8.ID == ControlID)
return c8;
if (depth > 9)
{
foreach (Control c9 in c8.Controls)
{
if (c9.ID == ControlID)
return c9;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return null;
}