LeetCode(力扣)题目中二叉树的如何生成?根据给定顺序列表生成二叉树(python)

在刷 leetcode 二叉树相关的题目时,经常有这样给定的例子,例如: 检查平衡性

实现一个函数,检查二叉树是否平衡。在这个问题中,平衡树的定义如下:任意一个节点,其两棵子树的高度差不超过 1。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
    3
   / \
  9  20
    /  \
   15   7
返回 true 。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
      1
     / \
    2   2
   / \
  3   3
 / \
4   4
返回 false 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/check-balance-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

如果我们想要在本地调试程序,就需要生成相应的二叉树,进而调试代码。然而,每次如果要手动添加 Node 来生成树是非常麻烦的。

根据示例,给我们的是一个分层顺序列表 类似于 [3,9,20,null,null,15,7]。我们可以非常直观的知道 3 是根结点, 9 和 20 是 3 的左右子节点, null 和 null 是 9 的左右子节点,15 和 7 是 20 的左右子节点。
从上面的描述中,可以发现分配左右节点的先后顺序也是 3,9,20,跟列表顺序是一致的,即先给 3 分配左右节点,再给 9 分配左右节点,再给 20 分配左右节点,如果列表更长,接下来会跳过null,给 15 分配左右节点,再给 7 分配左右节点。
因此,我们可以用队列来实现二叉树的初始化中这种先入先出的特点。下面的图示说明了队列初始化二叉树的过程:

拿到 3 ,放进队列

1

拿到 9,分配给 3 的左儿子,并且放进队列

2

拿到 20,分配给 3 的右节点,并且放进队列

3

3 已经分配好了左右节点,pop 出队列

LeetCode(力扣)题目中二叉树的如何生成?根据给定顺序列表生成二叉树(python)_第1张图片

拿到 null,分配给 9 的左节点,注意:null 不放入队列

LeetCode(力扣)题目中二叉树的如何生成?根据给定顺序列表生成二叉树(python)_第2张图片

拿到 null,分配给 9 的右节点

LeetCode(力扣)题目中二叉树的如何生成?根据给定顺序列表生成二叉树(python)_第3张图片

9 已经分配好了左右节点,pop 出队列

LeetCode(力扣)题目中二叉树的如何生成?根据给定顺序列表生成二叉树(python)_第4张图片

拿到 15,分配给 20 的左儿子,并且放进队列

LeetCode(力扣)题目中二叉树的如何生成?根据给定顺序列表生成二叉树(python)_第5张图片

拿到 7,分配给 20 的右儿子,并且放进队列

LeetCode(力扣)题目中二叉树的如何生成?根据给定顺序列表生成二叉树(python)_第6张图片

20 已经分配好了左右节点,pop 出队列

LeetCode(力扣)题目中二叉树的如何生成?根据给定顺序列表生成二叉树(python)_第7张图片

没有新的元素,因此到这一步返回根结点 3 即可。
最后代码如下:
# 节点类
class Node(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
# 树生成代码
def generate_tree(vals):
    if len(vals) == 0:
        return None
    que = [] # 定义队列
    fill_left = True # 由于无法通过是否为 None 来判断该节点的左儿子是否可以填充,用一个记号判断是否需要填充左节点
    for val in vals:
        node = Node(val) if val else None # 非空值返回节点类,否则返回 None
        if len(que)==0:
            root = node # 队列为空的话,用 root 记录根结点,用来返回
            que.append(node)
        elif fill_left:
            que[0].left = node
            fill_left = False # 填充过左儿子后,改变记号状态
            if node: # 非 None 值才进入队列
                que.append(node)
        else:
            que[0].right = node
            if node:
                que.append(node)
            que.pop(0) # 填充完右儿子,弹出节点
            fill_left = True # 
    return root
# 定义一个dfs打印中序遍历
def dfs(node):
    if node is not None:
        dfs(node.left)
        print(node.val, end=' ')
        dfs(node.right)
# 定义一个bfs打印层序遍历
def bfs(node):
    que = []
    que.append(node)
    while que:
        l = len(que)
        for _ in range(l):
            tmp = que.pop(0)
            print(tmp.val, end=' ')
            if tmp.left:
                que.append(tmp.left)
            if tmp.right:
                que.append(tmp.right)
        print('|', end=' ')

# test
null = None
vals = [3,9,20,null,null,15,7]
tree = generate_tree(vals) 
print('中序遍历:')    
dfs(tree) # 9 3 15 20 7 
print('\n层序遍历:')
bfs(tree) # 3 | 9 20 | 15 7 |

你可能感兴趣的:(二叉树,算法,二叉树,数据结构,算法,列表,队列)