后序遍历的访问顺序为 左子树->右子树->根节点
递归的方式很简单,这里就不叙述了,考虑非递归方式
思路:
后序遍历跟前序和中序不同的地方在于,访问完左子树后,会回溯到父节点,此时不能访问父节点,访问完右子树后,回溯到父节点,此时才能访问父节点。所以回溯到父节点的时候,要判断上一次操作访问的是哪里,如果上一次操作访问的时左子树,那么不可访问当前节点,得先去访问当前节点的右子树,如果上一次操作访问的是右子树,那么可以访问当前节点。因此,要有一个指针来记录上一次操作访问的是哪个节点。这个指针加入的位置就是访问节点的位置。
核心代码

        res = []
        pNode = self.root
        stack = []
        preVisited =None

        while(pNode != None or len(stack) != 0):
            if (pNode != None):
                stack.append(pNode)
                pNode = pNode.left
            else:
                pNode = stack[-1]
                if pNode.right == None or pNode.right == preVisited:
                    res.append(pNode.val)
                    stack.pop()
                    preVisited = pNode
                    pNode = None     #防止被重复访问

                else:
                    pNode = pNode.right

二叉树后序遍历递归与非递归
以节点4为例,因为节点4非空,压栈并访问其左子树,对于节点6,压栈,访问其左子树,以为左子树为None,看其父节点,因为父节点的右子树也为None,所以可以访问当前的父节点6(访问即出栈),并将节点6记为preVisited,并将pNode标记为None,这样可以避免下一次重复访问该节点。
进入下一轮循环后,因为pNode为None,要看此时栈顶的元素父节点4,并且其右子树不为空,且上次访问的节点不是节点7(上次访问的是6),此时进入右子树访问。访问完毕后preVisited更新为节点7,pNode为None。
进入下一轮循环,指针指向当前的父节点4,虽然其右子树不为空,但是其右孩子节点7是其上一次访问过的节点(pNode.right == preVisited),所以可以访问当前的父节点。

class Node:
    def __init__(self,val):
        self.val = val
        self.left = None
        self.right = None

class Traverse:
    def __init__(self):
        node1 = Node(1)
        node2 = Node(2)
        node3 = Node(3)
        node4 = Node(4)
        node5 = Node(5)
        node6 = Node(6)
        node7 = Node(7)

        node1.left = node2
        node1.right = node3
        node2.left = node4
        node2.right = node5
        node4.left = node6
        node4.right = node7
        self.root = node1
        self.resRec =[]

    def printResult(self):
        print([6, 7, 4, 5, 2, 3, 1])

    def postOrderTraverse(self):
        res = []
        pNode = self.root
        stack = []
        preVisited =None
        
        while(pNode != None or len(stack) != 0):
            if (pNode != None):
                stack.append(pNode)
                pNode = pNode.left
            else:
                pNode = stack[-1]
                if pNode.right == None or pNode.right == preVisited:
                    res.append(pNode.val)
                    stack.pop()
                    preVisited = pNode
                    pNode = None     #防止被重复访问

                else:
                    pNode = pNode.right
        print(res)

    def postOrderRecursion(self):
        self.helper(self.root)
        print(self.resRec)

    def helper(self,root):
        if root != None:
            self.helper(root.left)
            self.helper(root.right)
            self.resRec.append(root.val)

相关文章: