【问题标题】:Using Java's regular expression to identify tree node's children in parenthesized string.使用 Java 的正则表达式来识别带括号的字符串中的树节点的子节点。
【发布时间】:2023-03-09 09:51:01
【问题描述】:

我正在努力将带括号的字符串(例如 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 个叶子。

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

【问题讨论】:

标签: java regex tree


【解决方案1】:

用正则表达式是不可能的,见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 的情况下编写稍微简单的递归解析代码)

【讨论】:

  • 像魅力一样工作。两个注意事项:它应该是 tokenizer.nextToken() 并且 parseTree() 方法不应该是无效的。
  • 我有一个很奇怪的问题:你怎么知道怎么做的?这是您以前遇到过的事情,还是您只是知道 StreamTokenizer 对象能够做得如此出色以至于您很快就想出了这个解决方案?
  • 之前用过StreamTokenizer实现解析器,所以对它的能力比较熟悉
猜你喜欢
  • 2011-10-11
  • 1970-01-01
  • 1970-01-01
  • 2021-07-05
  • 2017-10-14
  • 2013-07-11
  • 1970-01-01
  • 2015-09-13
  • 1970-01-01
相关资源
最近更新 更多