二叉树的后序遍历-非递归版本-四种方法python

二叉树的后序遍历-非递归版本-四种方法python

文章目录

    • 二叉树的后序遍历-非递归版本-四种方法python
      • 方法1:利用两个栈实现
      • 方法2:利用一个栈和两个标志节点实现
      • 方法3:利用一个栈和两个标志节点实现(另一种)
      • 方法4:利用一个栈和一个标志节点实现
      • 验证结果

定义二叉树

class BinNode( ):
    def __init__( self, val ):
        self.lchild = None
        self.rchild = None
        self.value = val

方法1:利用两个栈实现

def bin_tree_post_order_traverse1( root):
    '''
    利用两个栈实现
    '''
    s1 = []
    s2 = []
    s1.append( root )
    while s1:
        node = s1.pop()
        s2.append( node )
        if node.lchild:
            s1.append( node.lchild )
        if node.rchild:
            s1.append( node.rchild )
    while s2:
        print(s2.pop().value)

方法2:利用一个栈和两个标志节点实现

def bin_tree_post_order_traverse2( root):
    '''
    利用一个栈和两个标志节点实现后序遍历
    '''
    curr = root
    prev = None
    s = []
    s.append( curr )
    while s:
        curr = s[-1]
        # 如果当前节点的左节点或者右节点不存在——这个条件针对叶子节点
        #    or 前一个节点是当前节点的左节点或右节点(遍历过了右节点或左节点——这个条件针对非叶子节点
        if ( not curr.lchild and not curr.rchild ) \
                or ( prev and ( prev == curr.lchild or prev == curr.rchild ) ):
            print( curr.value )
            s.pop()
            prev = curr
        else:
            if curr.rchild: #先右节点先入栈,左节点后入栈,这样判断栈顶的时候总是左节点先出
                s.append( curr.rchild )
            if curr.lchild:
                s.append( curr.lchild )

方法3:利用一个栈和两个标志节点实现(另一种)

def bin_tree_post_order_traverse3(root):
    '''
    利用一个栈和两个标志节点实现后序遍历
    '''
    s=[]
    s.append(root)
    cur=None
    prev=root
    while s:
        cur=s[-1]
        # 当前节点的左节点存在,且它的左节点和右节点都没有打印过
        if cur.lchild and prev!=cur.lchild and prev!=cur.rchild:
            s.append(cur.lchild)
        elif cur.rchild and prev!=cur.rchild:
            # 运行到这里表明当前节点的左节点已经打印过了
            s.append(cur.rchild)
        else:
            print(s[-1].value)
            s.pop()
            prev=cur

方法4:利用一个栈和一个标志节点实现

def bin_tree_post_order_traverse4(root):
    '''
    利用一个栈和一个标志节点实现后序遍历
    '''
    s=[]
    s.append(root)
    lastNode=None #上一个访问过(打印出来)的节点
    while s:
        while s[-1].lchild: # 使用while到达其分支最底层的左节点
            s.append(s[-1].lchild)
        while s:
            # 如果当前节点的右节点为空或者已经访问过时,此时当前节点已经遍历完成,出栈,并打印
            if s[-1].rchild==lastNode or not s[-1].rchild:
                node=s.pop()
                print(node.value)
                lastNode=node
            elif s[-1].rchild: #如果当前节点的右节点没有访问过,则当前节点入栈
                s.append(s[-1].rchild)
                break #当前节点入栈后,需要首先遍历其左节点,因此break,使用while到达其分支最底层的左节点

验证结果

binNode1 = BinNode( 1 )
binNode2 = BinNode( 2 )
binNode3 = BinNode( 3 )
binNode4 = BinNode( 4 )
binNode5 = BinNode( 5 )
binNode6 = BinNode( 6 )

binNode1.lchild = binNode2
binNode1.rchild = binNode3
binNode2.lchild = binNode4
binNode2.rchild = binNode5
binNode3.lchild = binNode6

print('方法1')
bin_tree_post_order_traverse1(binNode1)
print('方法2')
bin_tree_post_order_traverse2(binNode1)
print('方法3')
bin_tree_post_order_traverse3(binNode1)
print('方法4')
bin_tree_post_order_traverse4(binNode1)

输出

方法1
4
5
2
6
3
1
方法2
4
5
2
6
3
1
方法3
4
5
2
6
3
1
方法4
4
5
2
6
3
1

Reference
二叉树先中后序遍历_非递归cpp
https://www.cnblogs.com/tudas/p/binary-tree-traverse.html

你可能感兴趣的:(算法和数据结构)