我正在使用tree库,并且所需功能的一部分是能够在节点中搜索与模式匹配的子节点。
'pattern'是一个规范(或标准),它规定了结构,以及要匹配的子树中节点的属性。
例如,假设一棵树代表有关特定鸟类的数据。进一步假设这种树的节点具有以下属性:
鉴于父节点,我想以简单的英语发出搜索:
“取给我所有的雄性鸟类 这只鸟的后代,住在里面 XXX城市并且重量> 100克。发现的任何这样的鸟也应该至少有2个兄弟和一个妹妹,并且本身必须至少有一个孩子“
<注意>
为了澄清,我不希望能够像上面所做的那样使用普通英语进行查询。我只使用“普通英语查询”来说明我想在树上执行的匹配类型。我完全希望在实践中使用符号进行匹配(而不是纯文本)。
< / note>
我在考虑使用正则表达式模式匹配来匹配树。一种方法是使用每个节点的字符串表示,因此我可以使用普通的正则表达式 - 但这可能是非常低效的,因为会有大量重复的数据 - 即子节点的字符串表示将是超集他们的父表示,将是他们父母代表字符串的超集,依此类推,递归地,在树上 - 这对于事件适度大小的树很容易变得笨重 - 必须有更好的方法。
是否有人知道一种算法可以让我根据模式选择节点中的节点(子树)?
虽然我要求使用通用算法,但我在Python中实现了这一点。任何进一步说明这种算法的片段(如果确实可以写出来的话)都会非常有用。
答案 0 :(得分:4)
使用通配符编写Lisp Sexpression来描述树匹配有什么问题?括号将节点分组。从左到右的元素匹配根,后跟子项。子树匹配使用嵌套的Sexpressions来描述子树。
以下将匹配具有任意根节点的树,第一个子节点是叶子A,第三个子节点是以X为根的子树,第一个子节点1和第三个子节点A:
(?root A ? (X 1 A))
这个想法对我来说并不是独一无二的;自六十年代初以来,Lisp家伙一直在编写这样的模式。
这是一个LISP模式匹配器(作为一个你想要的例子),它只能追溯到20年前: http://norvig.com/paip/patmatch.lisp
然而,自己编码很容易。这通常被指定为学习LISP的人的家庭作业。
答案 1 :(得分:3)
这取决于你的树。如果您的树是有根和有序的,那么您应该能够在次线性时间内检查完全匹配,如果没有,您应该能够在线性时间内检查匹配。还存在几种更快的算法用于近似匹配。
要查找此类主题的材料和算法,Google Scholar是您的朋友。搜索子树匹配或类似匹配应该可以帮助您。
编辑:根据您更新的条目判断,我建议您查看XPath和类似查询语言的实现方式。 XML是一个有根的树,XPath可以使用复杂的匹配运算符(例如示例中的运算符)搜索该树中的子树。
我还建议你不要自己实现这个,而是使用现有的库(比如PyLucene或其他一些搜索引擎,根据你提出的例子,这似乎是合适的。)