二叉树的迭代后序遍历用单栈,如何解决这个问题?

问题描述 投票:0回答:1

我一直对算法和数据结构学习了,我写了一个二叉树后序遍历,而无需使用递归和只使用一个堆栈。

下面是代码:

def postorder_iterative(self):
    current = self
    s = []
    current1 = None
    done = 0
    def peek(s):
        return s[-1]

    while(not done):
        if current and (current != current1):
            s.append(current)
            current = current.leftChild
        elif(len(s) > 0):
            if peek(s).rightChild and peek(s).rightChild != current:
                current = peek(s).rightChild
            else:
                current = current1 = s.pop()
                print(current.key)
        else:
            done = 1

此代码实际工作,但我花了永远拿出它。

有人能解释什么是思考这个问题的直观的方式?

我希望能够重现它使用逻辑和我做了它不会花费太多的时间。

python iteration binary-search-tree tree-traversal postorder
1个回答
2
投票

后序遍历需要你只遍历左声道和右子树后打印当前节点的值。您正在使用的堆栈,只遍历左树,并使用current1变量(打印的最后一个节点)知道,你现在打了退堂鼓右手边的树,这样就可以打印出当前节点。

我会重新命名currentnodecurrent1last(去年印刷),除去peek()功能仅限于直接引用stack[-1]tos(堆栈的顶部),并简化您的方法:

def postorder_iterative(self):
    node, last = self, None
    stack = []

    while True:
        if node and node is not last:
            # build up the stack from the left tree
            stack.append(node)
            node = node.leftChild
        elif stack:
            # no more left-hand tree to process, is there a right-hand tree?
            tos = stack[-1]
            if tos.rightChild and tos.rightChild is not node:
                node = tos.rightChild
            else:
                # both left and right have been printed
                node = last = stack.pop()
                print(last.key)
        else:
            break

它仍然是难以遵循然而到底是怎么回事,因为last并在左,右子树已经处理了点之间的连接是不是所有的清楚。

我会使用一个单一的堆栈的状态标志,以跟踪过程中,你在哪里:

def postorder_iterative(self):
    new, left_done, right_done = range(3)   # status of node
    stack = [[self, new]]  # node, status

    while stack:
        node, status = stack[-1]
        if status == right_done:
            stack.pop()
            print(node.key)
        else:
            stack[-1][1] += 1 # from new -> left_done and left_done -> right_done
            # new -> add left child, left_done -> add right child
            next_node = [node.leftChild, node.rightChild][status]
            if next_node is not None:
                stack.append((next_node, new))

节点经过三种状态,简单地通过增加状态标志。他们开始为新的节点,然后发展到左边,然后右键,并在堆栈的顶部是在最后的状态,我们从栈中取出,并打印节点值。

当仍然在新的或左状态,我们添加的左边或右边的节点,如果存在的话,到堆栈作为一个新的节点。

另一种方法推右手树到当前节点之前的堆栈。再后来,当您返回到当前节点,已经从堆栈中取出它,你可以检测你仍然需要处理的右侧,因为堆栈的顶部将有右手节点的情况。在这种情况下,只需更换堆栈与当前节点的顶部,并从那里继续;稍后您将回到同一个地方,将不再有对堆栈的顶部右侧节点,以便您可以打印:

def postorder_iterative(self):
    stack = []
    node = self

    while node or stack:
        while node:
            # traverse to the left, but add the right to the stack first
            if node.rightChild is not None:
                stack.append(node.rightChild)
            stack.append(node)
            node = stack.leftChild

        # left-hand tree traversed, time to process right or print
        node = stack.pop()

        if stack and node.rightChild is stack[-1]:
            # right-hand tree present and not yet done, swap tos and node
            node, stack[-1] = stack[-1], node
        else:
            print(node.key)
            node = None
© www.soinside.com 2019 - 2024. All rights reserved.