从上到下逐行遍历C#中的树

时间:2010-08-19 03:28:11

标签: c# recursion tree

最近朋友提出的有趣问题:想象一下,你有一个List< NodeType>树中的所有节点。您将如何从行根节点向下遍历树,以便您找到具有特定值的第一个节点。所以说每个节点都有3个属性:它的名称/位置,它的父节点的身份,以及谁“拥有”节点。问题是你想在树中找到你所拥有的最高节点,无论它在哪个分支上。我理解基本逻辑,以找到第一组子项,查找父项设置为第一个节点的所有节点。但是你将如何递归搜索List<>节点找到你拥有的最高节点?

4 个答案:

答案 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;
        }