我需要帮助开发这个我正在研究的算法。我有一个以下格式输入树:
(Root(AB(ABC)(CBA))(CD(CDE)(FGH)))
这看起来是以下树。
Root
|
____________
AB CD
| |
__________ ___________
ABC CBA CDE FGH
算法假设读取括号格式并给出以下输出:
Root -> AB CD
AB -> ABC CBA
CD -> CDE FGH
列出了根及其子女和所有其他有孩子的父母。 我无法理解如何开始这个,有人可以帮我提供一些提示或提供一些参考或链接吗?
答案 0 :(得分:2)
解决方案:来自模块Tree
的{{1}}类
(又名自然语言工具包)
进行实际解析
这是你的意见:
nltk
你可以通过以下方式解析它:
input = '( Root ( AB ( ABC ) ( CBA ) ) ( CD ( CDE ) ( FGH ) ) )'
使用已解析的树
from nltk import Tree
t = Tree.fromstring(input)
如您所见,您可以将每个节点视为子树列表。
要漂亮打印树
>>> t.label()
'Root'
>>> len(t)
2
>>> t[0]
Tree('AB', [Tree('ABC', []), Tree('CBA', [])])
>>> t[1]
Tree('CD', [Tree('CDE', []), Tree('FGH', [])])
>>> t[0][0]
Tree('ABC', [])
>>> t[0][1]
Tree('CBA', [])
>>> t[1][0]
Tree('CDE', [])
>>> t[1][1]
Tree('FGH', [])
获取您想要的输出
>>> t.pretty_print()
Root
_______|________
AB CD
___|___ ___|___
ABC CBA CDE FGH
| | | |
... ... ... ...
<强>用法:强>
from sys import stdout
def showtree(t):
if (len(t) == 0):
return
stdout.write(t.label() + ' ->')
for c in t:
stdout.write(' ' + c.label())
stdout.write('\n')
for c in t:
showtree(c)
安装模块
>>> showtree(t)
Root -> AB CD
AB -> ABC CBA
CD -> CDE FGH
(如果需要,请使用pip install nltk
)
答案 1 :(得分:0)
我认为在Python中解析最流行的解决方案是PyParsing。 PyParsing带有解析S表达式的语法,你应该能够使用它。在StackOverflow中回答:
答案 2 :(得分:0)
递归下降解析器是一种解析器的简单形式,可以解析许多语法。虽然整个解析理论对于堆栈溢出答案来说太大了,但最常用的解析方法包括两个步骤:首先,令牌化,它提取字符串的子词(这里可能是“Root”和“ABC”之类的词) ,或括号如'('和')'),然后使用递归函数进行解析。
这段代码解析输入(就像你的例子一样),产生一个所谓的解析树,并且还有一个函数'show_children',它接受解析树,并根据你的问题产生表达式的子视图。
import re
class ParseError(Exception):
pass
# Tokenize a string.
# Tokens yielded are of the form (type, string)
# Possible values for 'type' are '(', ')' and 'WORD'
def tokenize(s):
toks = re.compile(' +|[A-Za-z]+|[()]')
for match in toks.finditer(s):
s = match.group(0)
if s[0] == ' ':
continue
if s[0] in '()':
yield (s, s)
else:
yield ('WORD', s)
# Parse once we're inside an opening bracket.
def parse_inner(toks):
ty, name = next(toks)
if ty != 'WORD': raise ParseError
children = []
while True:
ty, s = next(toks)
if ty == '(':
children.append(parse_inner(toks))
elif ty == ')':
return (name, children)
# Parse this grammar:
# ROOT ::= '(' INNER
# INNER ::= WORD ROOT* ')'
# WORD ::= [A-Za-z]+
def parse_root(toks):
ty, _ = next(toks)
if ty != '(': raise ParseError
return parse_inner(toks)
def show_children(tree):
name, children = tree
if not children: return
print '%s -> %s' % (name, ' '.join(child[0] for child in children))
for child in children:
show_children(child)
example = '( Root ( AB ( ABC ) ( CBA ) ) ( CD ( CDE ) ( FGH ) ) )'
show_children(parse_root(tokenize(example)))
答案 3 :(得分:0)
试试这个:
def toTree(expression):
tree = dict()
msg =""
stack = list()
for char in expression:
if(char == '('):
stack.append(msg)
msg = ""
elif char == ')':
parent = stack.pop()
if parent not in tree:
tree[parent] = list()
tree[parent].append(msg)
msg = parent
else:
msg += char
return tree
expression = "(Root(AB(ABC)(CBA))(CD(CDE)(FGH)))"
print toTree(expression)
它返回一个字典,可以使用键''访问 root 。然后,您可以使用简单的BFS打印输出。
输出:
{
'' : ['Root'],
'AB' : ['ABC', 'CBA'],
'Root': ['AB', 'CD'],
'CD' : ['CDE', 'FGH']
}
在开始之前,您必须消除Expression中的所有空格,或者通过添加以下内容作为for循环中的第一行来忽略表达式中的相关字符:
if char == <IRRELEVANT CHARACTER>:
continue
上面的代码将在O(n)时间内运行,其中n是表达式的长度。
修改强>
这是打印功能:
def printTree(tree, node):
if node not in tree:
return
print '%s -> %s' % (node, ' '.join(child for child in tree[node]))
for child in tree[node]:
printTree(tree, child)
可以通过以下方式实现所需的输出:
expression = "(Root(AB(ABC)(CBA))(CD(CDE)(FGH)))"
tree = toTree(expression)
printTree(tree, tree[''][0])
<强>输出强>
Root -> AB CD
AB -> ABC CBA
CD -> CDE FGH
修改强>
假设节点名称不是唯一的,我们只需要给节点赋予新名称。这可以使用:
完成def parseExpression(expression):
nodeMap = dict()
counter = 1
node = ""
retExp =""
for char in expression:
if char == '(' or char == ')' :
if (len(node) > 0):
nodeMap[str(counter)] = node;
retExp += str(counter)
counter +=1
retExp += char
node =""
elif char == ' ': continue
else :
node += char
return retExp,nodeMap
打印功能现在将更改为:
def printTree(tree, node, nodeMap):
if node not in tree:
return
print '%s -> %s' % (nodeMap[node], ' '.join(nodeMap[child] for child in tree[node]))
for child in tree[node]:
printTree(tree, child, nodeMap)
可以使用以下方法获得输出:
expression = " ( Root( SQ ( VBZ ) ( NP ( DT ) ( NN ) ) ( VP ( VB ) ( NP ( NN ) ) ) ))"
expression, nodeMap = parseExpression(expression)
tree = toTree(expression)
printTree(tree, tree[''][0], nodeMap)
输出:
Root -> SQ
SQ -> VBZ NP VP
NP -> DT NN
VP -> VB NP
NP -> NN