将递归树行走函数转换为迭代

时间:2016-08-10 20:26:34

标签: python recursion tree iteration

如何将以下递归函数walk()转换为迭代函数?

迭代地以相同的顺序遍历节点很容易使用堆栈,但是我无法弄清楚如何编写迭代函数,它将打印每个节点的开始和结束标记,就像递归版本一样。 / p>

代码:

class Node(object):
    def __init__(self, name, children=[]):
        self.name = name
        self.children = children

def walk(node):
    print('<', node.name, '>', sep='')
    for n in node.children:
        walk(n)
    print('</', node.name, '>', sep='')

root = \
Node('html', [
    Node('head'),
    Node('body', [
        Node('div'),
        Node('p', [
            Node('a'),
        ])
    ]),
])

walk(root)

输出:

<html>
<head>
</head>
<body>
<div>
</div>
<p>
<a>
</a>
</p>
</body>
</html>

迭代遍历树的代码:

该函数以正确的顺序访问节点,但显然不会打印结束标记。

def walk(node):
    stack = []
    stack.append(node)
    while len(stack) > 0:
        node = stack.pop()
        for child in reversed(node.children):
            stack.append(child)
        print(node.name)

2 个答案:

答案 0 :(得分:0)

问题是,为了使其工作,您还需要在节点结束的堆栈上进行记录。可能的解决方案是:

 lst <- mget(ls(pattern = "\\.value$"))
 names(lst) <- sub("\\.value$", "", names(lst))

我已经添加了缩进功能,因此输出效果更好:

def walk(root):
    stack = []
    stack.append(root)
    indent = 0
    while stack:
        node = stack.pop()
        if isinstance(node, Node):
            print('    ' * indent, "<", node.name, ">", sep="")
            indent += 1
            stack.append(node.name)
            stack.extend(reversed(node.children))
        else:
            indent -= 1
            print('    ' * indent, "</", node, ">", sep="")

答案 1 :(得分:0)

有点post-order tree treversal ,因为你必须在访问子节点后访问父节点。

我修改了几行现有代码:

class Node(object):
def __init__(self, name, children=[]):
    self.name = name
    self.children = children

# def walk(node):
#     print('<', node.name, '>', sep='')
#     for n in node.children:
#         walk(n)
#     print('</', node.name, '>', sep='')

def walk(node):
    stack = []
    stack.append((node, 'start'))
    while len(stack) > 0:
        node, status = stack.pop()
        if status == 'start':
            stack.append((node, 'end'))
            for child in reversed(node.children):
                stack.append((child, 'start'))
            print('<', node.name, '>', sep='')
        else: # status == 'end'
            print('</', node.name, '>', sep='')

root = \
Node('html', [
    Node('head'),
    Node('body', [
        Node('div'),
        Node('p', [
            Node('a'),
        ])
    ]),
])

walk(root)