二叉树遍历及变形

1. 定义

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

2. 遍历

2.1 先序遍历

2.1.1 递归

def pre(node):
    if node is None:
        return
    print(node.val)
    pre(node.left)
    pre(node.right)

2.1.2 非递归

def pre1(node):
    if node is None:
        return
    stack = [node]
    while stack:
        # 取出栈顶元素
        node = stack.pop()
        # node = stack.pop(-1)
        print(node.val)

        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)
或(不如上面的简单)
def pre2(node):
    if node is None:
        return
    stack = []
    while (node is not None) or (len(stack) > 0):
        if node:
            stack.append(node)
            # yield node.val
            print(node.val)
            node = node.left
        else:
            node = stack.pop()
            node = node.right

2.3 中序遍历

2.3.1 递归

def mid(node):
    if node is None:
        return
    mid(node.left)
    print(node.val)
    mid(node.right)

2.3.2 非递归

def mid1(node):
    if node is None:
        return
    stack = []
    while node or (len(stack) > 0):
        if node:
            stack.append(node)
            node = node.left
        else:
            node = stack.pop()
            print(node.val)
            node = node.right

2.3 后序遍历

2.3.1 递归

def post(node):
    if node is None:
        return
    post(node.left)
    post(node.right)
    print(node.val)

2.3.2 非递归

stack1 入(根左右) --> stack1出(根右左) --倒置--> stack2(左右根)

def post1(node):
    if node is None:
        return
    stack1, stack2 = [], []
    stack1.append(node)
    while stack1:
        node = stack1.pop()
        stack2.append(node)
        if node.left:
            stack1.append(node.left)
        if node.right:
            stack1.append(node.right)
    while stack2:
        node = stack2.pop()
        print(node.val)

2.4 测试

# 定义结点
node1 = TreeNode(1)
node2 = TreeNode(2)
node3 = TreeNode(3)
node4 = TreeNode(4)
node5 = TreeNode(5)
node6 = TreeNode(6)
node7 = TreeNode(7)
# 构建树
root = node1
root.left = node2
root.right = node3
node2.left = node4
node2.right = node5
node3.left = node6
node3.right = node7
print(------先序遍历(递归)------)
pre(root)
pre1(root)
# 1 2 4 5 3 6 7
print(------中序遍历(递归)------)
mid(root)
# 4 2 5 1 6 3 7
print(------后序遍历(递归)------)
post(root)
# 4 5 2 6 7 3 1

3. 重建二叉树

只能由前中序或后中序才能重建二叉树(必须有中序遍历找到根结点所在位置)。

3.1 由前、中序遍历重建二叉树

def tree_by_pre_mid(pre, mid):
    if (len(pre) == 0) or (len(mid) == 0) or (len(pre) != len(mid)):
        return
    root = TreeNode(pre[0])
    # 在中序遍历中找到根结点位置
    i = mid.index(pre[0])
    root.left = tree_by_pre_mid(pre[1:i+1], mid[:i])
    root.right = tree_by_pre_mid(pre[i+1:], mid[i+1:])
    return root

3.2 由后、中序遍历重建二叉树

def tree_by_post_mid(post, mid):
    if (len(post) == 0) or (len(mid) == 0) or (len(post) != len(mid)):
        return
    root = TreeNode(post[-1])
    # 在中序遍历中找到根结点位置
    i = mid.index(post[-1])
    root.left = tree_by_post_mid(post[:i], mid[:i])
    # -1 不能省,否则结果不对
    root.right = tree_by_post_mid(post[i:-1], mid[i+1:])
    return root

3.3 测试

pre_order_list = [1, 2, 4, 5, 3, 6, 7]
mid_order_list = [4, 2, 5, 1, 6, 3, 7]
post_order_list = [4, 5, 2, 6, 7, 3, 1]
root = tree_by_pre_mid(pre_order_list, mid_order_list)
post(root)
# 4 5 2 6 7 3 1
root = tree_by_post_mid(post_order_list, mid_order_list)
pre(root)
# 1 2 4 5 3 6 7

4. 广度优先与深度优先遍历

4.1 广度优先遍历BFS(层次遍历)

依次将根、左、右子树入队列。

def level(node):
    if node is None:
        return
    queue = [node]
    while queue:
        # 取出队头元素
        node = queue.pop(0)
        print(node.val)
        if node.left:
            queue.append(node.left)
        if node.right:
            queue.append(node.right)

4.2 深度优先遍历(DFS)

二叉树的深度优先遍历与先序遍历是一样的!!!

4.3 测试

node1 = TreeNode(1)
node2 = TreeNode(2)
node3 = TreeNode(3)
node4 = TreeNode(4)
node5 = TreeNode(5)
node6 = TreeNode(6)
node7 = TreeNode(7)
    
root = node1
root.left = node2
root.right = node3
node2.right = node4
node3.left = node5
node3.right = node6
node5.left = node7

level(root)
# 1 2 3 4 5 6 7

5. 之字形遍历(锯齿形层次遍历)

二叉树宽度也是这个思路:先求按层遍历的数组,再求数组内子数组长度最大的那层既是。

def zigzag_level_order(root):
    if not root:
        return []
    queue = [root]
    result = []
    # 相邻层flag取反
    flag = 1
    while queue:
        # 存储当前层遍历的结果
        temp_list = []
        for i in range(len(queue)):
            temp = queue.pop(0)
            temp_list.append(temp.val)
            if temp.left:
                queue.append(temp.left)
            if temp.right:
                queue.append(temp.right)

        if flag == -1:
            temp_list = temp_list[::-1]
        result.extend(temp_list)
        # result.append(temp_list)
        flag *= -1
    print(result)

测试

node1 = TreeNode(1)
node2 = TreeNode(2)
node3 = TreeNode(3)
node4 = TreeNode(4)
node5 = TreeNode(5)
node6 = TreeNode(6)
node7 = TreeNode(7)
root = node4
root.left = node2
root.right = node6
# node2.left = node1
node2.right = node3

# node3.right = node7
node6.left = node5
zigzag_level_order(root)
# [4, 6, 2, 3, 5]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值