Python 二叉树先序中序后序遍历 非递归

先序遍历二叉树非递归

       类似递归的思想,遇到一个节点先打印出来,然后依次访问左右节点。但是非递归借助栈来实现有所不同,应该先打印当前节点,然后依次入栈右节点和左节点,因为此时栈的插入顺序和弹出顺序相反。

       节点的结构:

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

       先序遍历的Python代码:

def pre_order(head):
    '''
    二叉树先序遍历非递归实现
    :param head: 头节点
    :return: result列表类型
    '''
    if not head: # 空
        return []
    stack, result = [], []
    stack.append(head)
    while len(stack) != 0:
        node = stack.pop() # 先序 遇到就先输出
        result.append(node.val)
        # 栈的弹出顺序与入栈顺序相反 因此先入右再入左
        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)
    return result

中序遍历二叉树非递归

       中序遍历就不能马上打印当前节点了,得先打印左孩子的节点,所以得先把有左孩子的节点压栈。从头结点开始,不断把有左孩子的节点压栈,直到左孩子为空,这样能保证先打印出左下角的节点。如果当前节点没有左孩子了,就出栈打印一个出来。如果这个节点有右节点,就继续上一步骤,对有左子树的疯狂压栈。

      复杂点来说,就是把有左节点的疯狂压栈,没了就弹一个出来打印,再看看有没有右节点,有就转到右节点,然后再重复左节点的疯狂压栈~~~

def mid_order(head):
    '''
    二叉树中序遍历非递归实现
    1.当前节点如有左节点就不断压栈 无左节点就可以出栈打印
    2.打印出栈的节点若有右子树则将右节点执行1的步骤
    :param head: 头结点
    :return: result列表类型
    '''
    if not head: #空
        return []
    stack, result = [], []
    node = head
    # 循环条件:1.栈非空则还可以输出 2.栈空但是节点非空说明还有节点可以压栈
    while node or len(stack) != 0:
        if not node: # 如果节点为空 证明没有左子树 弹出一个
            node = stack.pop()
            result.append(node.val)
            node = node.right #尝试是否有右节点
        else: # 节点非空 压栈 尝试是否有左子树
            stack.append(node)
            node = node.left
    return result

后序遍历二叉树非递归

       后序遍历是 左-右-中 的顺序,反过来就是 中-右-左,这就是二叉树镜像(左右节点互换)的先序遍历顺序。也就是说,镜像二叉树的先序遍历逆序后就是二叉树后序遍历的顺序。所以在刚才先序遍历的代码基础上,改一下左右节点入栈顺序,再在最后逆序一下就可以了。

def post_order(head):
    '''
    后序遍历二叉树非递归 后序遍历是 左-右-中
    反过来就是 中-右-左 其实就是先序遍历镜像二叉树(即左右互换)
    :param head: 头节点
    :return: result[::-1] 逆序
    '''
    if not head:
        return []
    stack, result = [], []
    stack.append(head)
    while len(stack) != 0:
        node = stack.pop() # 先序 遇到就先输出
        result.append(node.val)
        # 先压栈左节点再压右节点 所以输出就是先右后左
        if node.left:
            stack.append(node.left)
        if node.right:
            stack.append(node.right)
    return result[::-1] # 将 中-右-左 逆序变为 左-右-中

        最后附上全部代码,含测试案例

# -*- coding:utf-8 -*-
'''
    author: James_J
    time: 2020/02/21
'''


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


def pre_order(head):
    '''
    二叉树先序遍历非递归实现
    :param head: 头节点
    :return: result列表类型
    '''
    if not head: # 空
        return []
    stack, result = [], []
    stack.append(head)
    while len(stack) != 0:
        node = stack.pop() # 先序 遇到就先输出
        result.append(node.val)
        # 栈的弹出顺序与入栈顺序相反 因此先入右再入左
        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)
    return result


def mid_order(head):
    '''
    二叉树中序遍历非递归实现
    1.当前节点如有左节点就不断压栈 无左节点就可以出栈打印
    2.打印出栈的节点若有右子树则将右节点执行1的步骤
    :param head: 头结点
    :return: result列表类型
    '''
    if not head: #空
        return []
    stack, result = [], []
    node = head
    # 循环条件:1.栈非空则还可以输出 2.栈空但是节点非空说明还有节点可以压栈
    while node or len(stack) != 0:
        if not node: # 如果节点为空 证明没有左子树 弹出一个
            node = stack.pop()
            result.append(node.val)
            node = node.right
        else: # 节点非空 压栈 尝试是否有左子树
            stack.append(node)
            node = node.left
    return result


def post_order(head):
    '''
    后序遍历二叉树非递归 后序遍历是 左-右-中
    反过来就是 中-右-左 其实就是先序遍历镜像二叉树(即左右互换)
    :param head: 头节点
    :return: result[::-1] 逆序
    '''
    if not head:
        return []
    stack, result = [], []
    stack.append(head)
    while len(stack) != 0:
        node = stack.pop() # 先序 遇到就先输出
        result.append(node.val)
        # 先压栈左节点再压右节点 所以输出就是先右后左
        if node.left:
            stack.append(node.left)
        if node.right:
            stack.append(node.right)
    return result[::-1] # 将 中-右-左 逆序变为 左-右-中



if __name__ == '__main__':
    l1 = TreeNode(1)
    l2 = TreeNode(2)
    l3 = TreeNode(3)
    l4 = TreeNode(4)
    l5 = TreeNode(5)
    l6 = TreeNode(6)

    l1.left = l2
    l1.right = l3

    l2.left = l4
    l2.right = l5

    l3.left = l6
    print('pre_order', pre_order(l1))
    print('mid_order', mid_order(l1))
    print('post_order', post_order(l1))

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值