如何解析树的一行字符串表示?

时间:2016-04-22 15:26:21

标签: c# .net algorithm data-structures tree

我给了一个树的一行字符串表示。树中的键是整数。键是唯一的(但很稀疏)。例如字符串

2[5],3[6,12[15,16]]

描述树

2
\-- 5
3
|-- 6
`-- 12
    |-- 15
    `-- 16

我想用一个GetChildren方法将一行字符串解析为一个ChildLookup类,以便

  • GetChildren(2)返回[5]
  • GetChildren(5)返回[]
  • GetChildren(3)返回[6,12]
  • GetChildren(10)抛出KeyNotFoundException

我该怎么做?

动机:我正在尝试使用相同的API对为不同类编写的算法进行单元测试。

3 个答案:

答案 0 :(得分:1)

类似的东西:

  1. 扫描树中的父键。如果找不到,则返回null。
  2. 从下一个打开的括号中,您将添加到子输出列表。
  3. 从这里跟踪打开/关闭括号,作为树的深度。
  4. 当您处于父母以下的级别时,只会添加到您的返回列表中。
  5. 当然,您可以构建整个树,但这可能比您需要的更多。

答案 1 :(得分:0)

这是一个ersatz LR词法分析器/解析器(在Python中,但移植应该很容易)。假定有效输入。

#!/usr/bin/env python3
import re


def parse(s):
    children = {}
    stack = []
    for token in re.findall('[+-]?[0-9]+|.', s):
        if token == '[':
            stack.append(n)
        elif token == ']':
            del stack[-1]
        elif token != ',':
            n = int(token)
            children[n] = []
            if stack:
                children[stack[-1]].append(n)
    return children


>>> print(parse('2[5],3[6,12[15,16]]'))
{16: [], 2: [5], 3: [6, 12], 5: [], 6: [], 12: [15, 16], 15: []}

答案 2 :(得分:0)

您可以编写状态机解析器来构建树。

开始声明null这样的类:

Node

然后将输入格式化为从根节点开始:

public class Node
{
    public Node Parent;
    public string Value;
    public List<Node> SubNodes;
}

解析器将是这样的:

var input = "2[5],3[6,12[15,16]]";
var tree = string.Format("root[{0}]", input);

结果树是这样的:

Node root = new Node { Parent = null, Value = string.Empty, SubNodes = new List<Node>() };
Node node = root;

foreach (char c in tree)
{
    switch (c)
    {
        case '[':        // Start a new node, child of the current node 
            node = new Node { Parent = node, Value = string.Empty, SubNodes = new List<Node>() };
            node.Parent.SubNodes.Add(node);
            break;
        case ',':        // Start a new node, but at the same level of the current node
            node = new Node { Parent = node.Parent, Value = string.Empty, SubNodes = new List<Node>() };
            node.Parent.SubNodes.Add(node);
            break;
        case ']':        // Back to parent of the current node
            node = node.Parent;
            break;
        default:         // Add char to current node value
            node.Value += c;
            break;
    }
}

最后你的root |--2 | |--5 | |--3 |--6 |--12 |--15 |--16 就是这样:

ChildLookup