【问题标题】:Traversing a complex tree structure遍历复杂的树结构
【发布时间】:2012-02-26 22:47:36
【问题描述】:

我有一个这样的树结构:

A (20,40)
    B (21,22)
    C (23,33)
        D (24,29)
            E (25,26)
            F (27,28)
        G (30,31)
        H (32,33)
    I (34,37)
        J(35,36)
    K (38,39)

级别可以很深,所以我需要使用递归。如何找到给定节点的子节点及其级别值(例如,“B”将是级别 2)?

我很困惑这个问题,但到目前为止我的伪代码大致是这样的:

传入一个节点 --> 如果它的左值和右值的差> 1,则使用左值+1找到下一个子节点

【问题讨论】:

  • 这些实际上存储在一个简单的数组或列表中吗?对于 n 元树,我认为您最好构建/使用由节点组成的实际树结构,这些节点引用 (a) 父节点、(b) 可选的、兄弟节点和 (c) 后代节点。
  • 你会得到一个更快的答案是你发布了节点的(简化的)类定义和方法的大纲。

标签: c# recursion tree


【解决方案1】:

有很多方法可以做到这一点!看看Tree traversal 的想法。

从您的示例看来,您应该在每个节点上使用一些范围。

只是为了好玩,我尝试(非常快速地)构建一些代码 - 同样,这是在不知道您在搜索中使用哪些参数的情况下完成的。请注意,这只是一个示例,构建速度非常快:

节点结构

class Node
{
    public int Min { get; set; }
    public int Max { get; set; }

    public List<Node> Children { get; set; }

    public Node(int min, int max)
    {
        this.Min = min;
        this.Max = max;
        this.Children = new List<Node>();
    }

    public void Add(Node child)
    {
        this.Children.Add(child);
    }
}

一个主类

该类包含一个用于构建树的函数(不漂亮),以及一个递归函数,并返回级别,并输出节点对象。

class Program
{
    static void Main(string[] args)
    {
        var tree = GetTree();
        Node node;
        var val = Find(tree, 21, 1, out node);

        Console.WriteLine("depth: {0}", val);
        Console.WriteLine("\t{0}, {1}", node.Min, node.Max);
        Console.ReadKey();
    }

    private static int Find(Node curNode, int value, int level, out Node foundNode)
    {
        foundNode = curNode;
        foreach (var child in curNode.Children)
        {
            if (child.Min <= value && child.Max >= value)
                return Find(child, value, level + 1, out foundNode);
        }
        return level;
    }

    private static Node GetTree()
    {
        var a = new Node(20, 40);
        var b = new Node(21, 22);
        var c = new Node(23, 33);
        var d = new Node(24, 29);
        var e = new Node(25, 26);
        var f = new Node(27, 28);
        var g = new Node(30, 31);
        var h = new Node(32, 33);
        var i = new Node(34, 37);
        var j = new Node(35, 36);
        var k = new Node(38, 39);

        d.Add(e);
        d.Add(f);

        c.Add(d);
        c.Add(g);
        c.Add(h);

        i.Add(j);

        a.Add(b);
        a.Add(c);
        a.Add(i);
        a.Add(k);

        return a;
    }
}

private static Node GetTree()
{
    var a = new Node(20, 40);
    var b = new Node(21, 22);
    var c = new Node(23, 33);
    var d = new Node(24, 29);
    var e = new Node(25, 26);
    var f = new Node(27, 28);
    var g = new Node(30, 31);
    var h = new Node(32, 33);
    var i = new Node(34, 37);
    var j = new Node(35, 36);
    var k = new Node(38, 39);

    d.Add(e);
    d.Add(f);

    c.Add(d);
    c.Add(g);
    c.Add(h);

    i.Add(j);

    a.Add(b);
    a.Add(c);
    a.Add(i);
    a.Add(k);

    return a;
}

【讨论】:

    【解决方案2】:

    您总是可以使用正则表达式,对吗? :)

    您可以为此进行全局匹配:

    ([    ]+)([A-Z]+) \(\d+,\d+\)
    

    并统计这四个空格重复了多少次,基本就是字母的层次。

    如果要存储实际的树,还必须保留父节点的记录。

    【讨论】:

    • 我认为结构是用 ASCII 说明的,而实际的结构是在对象中?
    • @aweis 哦,我没想到,我猜你可能是对的。虽然适用于解析文本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    相关资源
    最近更新 更多