【问题标题】:Convert recursive tree walking function to iterative将递归树行走函数转换为迭代
【发布时间】:2016-12-17 09:35:41
【问题描述】:

下面的递归函数walk()如何转化为迭代函数?

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

代码:

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)

【问题讨论】:

  • 展示你的迭代函数,它只能部分解决问题。

标签: python recursion tree iteration


【解决方案1】:

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

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="")

我添加了缩进,所以输出更好:

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

【讨论】:

    【解决方案2】:

    有点像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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-08
      • 2015-05-30
      • 2014-03-01
      相关资源
      最近更新 更多