使用Java的正则表达式来识别带括号的字符串中的树节点的子节点。

时间:2013-11-03 22:38:45

标签: java regex tree

我正在努力将带括号的字符串(例如f(d(a c(b))e))转换为Java中的Tree数据结构(我正在研究一种允许使用字符串表示来实例化Tree的方法)。在上面的字符串中,f是树的根节点,它分支到d的子树和e的叶节点。在我能够将f标识为当前节点的标签后,我留下了d(a c(b))e

我希望能够使用Java的正则表达式来识别孩子;在这种情况下,d(a c(b))e。因此,要求如下。

在字符串中,单个字符可能会或可能不会被括号括起来。如果后跟括号,则返回内部的所有子字符串,即使它包含嵌套的括号。因此,正则表达式将匹配d(a c(b))e

此外,我希望这不仅仅适用于有两个孩子的节点。可能带括号的字符串可能是f(a b c),这是一个以f为根,有3个叶子的树。

到目前为止,我有.\(?[^\(\)]\)?,但这不起作用。

1 个答案:

答案 0 :(得分:4)

使用正则表达式是不可能的,请参阅Can regular expressions be used to match nested patterns?

使用StreamTokenizer和递归代替,应该看起来与此类似(未经测试):

public class Node {
  private String name;
  private ArrayList<Node> children = new ArrayList<Node>();

  public static Node parseTree(String s) throws IOException {
    StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(s));
    tokenizer.nextToken();                 // Move to first token
    Node result = new Node(tokenizer);     // Parse root node (and children)
    if (tokenizer.ttype != StreamTokenizer.TT_EOF) {
      throw new RuntimeException("Leftover token: "+ tokenizer.ttype);
    }
    return result;
  }

  Node(StreamTokenizer tokenizer) throws IOException {
    if (tokenizer.ttype != StreamTokenizer.TT_WORD) {
      throw new RuntimeException("identifier expected; got: " + tokenizer.ttype);
    }
    name = tokenizer.sval;                  // read then name 
    if (tokenizer.nextToken() == '(') {     // Consume the name and check for Children
      tokenizer.nextToken();                // Yes, consume '('
      do {
        children.add(new Node(tokenizer));  // Add and parse a child
      } while (tokenizer.ttype != ')');     // Until we reach ')'
      tokenizer.nextToken();                // Consume ')'
    }
  }
}

(如果节点名称都是单个字符且分隔符始终只是一个空格,则可以在没有StreamTokenizer的情况下编写稍微简单的递归解析代码)