1. 题目
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行在按照从左到右的顺序打印,其他行以此类推。例如,按之字形顺序打印下图中的二叉树。
打印结果为:
1
3 2
4 5 6 7
15 14 13 12 11 10 9 8
2. 解题思路
2.1 我的思路
使用的容器不变,仍然使用队列来实现。根据节点所处层数的不同而修改元素添加的顺序,打印的时候仍然顺序打印出来。
我们需要三个变量:
一个变量表示在当前层中还没有打印的节点数;
一个变量表示下一层节点的数目。
一个变量来记录这是第几行,奇数行如何如何,偶数行如何如何。
2.2 书中的思路
不使用队列来实现,而是使用栈来实现,而元素添加的顺序仍然需要考虑所处的层数。
这里是引用
3. 代码实现
3.1 我的思路
def print_binarytree(root):
"""
:param root: 二叉树的根节点
:return None
"""
if not root:
return
queue = [] # 队列
queue.append(root)
to_be_print = 1 # 表示当前层中还没有打印的节点数
next_level = 0 # 表示下一层节点的数目
level = 1 # 第几层
while queue:
cur_node = queue.pop(0) # 时间复杂度为O(n)
print(cur_node.value)
if level % 2: # 奇数,从左到右打印
if cur_node.left:
queue.append(cur_node.left)
next_level += 1 # 下一层有左子节点,下一层节点数目+1
if cur_node.right:
queue.append(cur_node.right)
next_level += 1 # 下一层有右子节点,下一层节点数目+1
else:
if cur_node.right:
queue.append(cur_node.right)
next_level += 1 # 下一层有右子节点,下一层节点数目+1
if cur_node.left:
queue.append(cur_node.left)
next_level += 1 # 下一层有左子节点,下一层节点数目+1
# 每打印一个节点,to_be_print减1
to_be_print -= 1
# 如果to_be_print == 0表示这一层已经打印完毕,需要打印下一行了
if to_be_print == 0:
print('\n') # 换行
level += 1
to_be_print = next_level # 下一层需要打印的节点数变成了当前层中还没有打印的节点数
next_levle = 0 # 同时清零下一层需要打印的节点数
3.2 书中的思路
def print_binarytree(root):
"""
:param root: 二叉树的根节点
:return None
"""
if not root:
return
#level = 1 # 第几层
cur_stack = [] # 栈
next_stack = [] # 栈
cur_stack.append(root)
while cur_stack:
cur_node = cur_stack.pop() # 后进先出,时间复杂度为O(n)
print(cur_node.value)
if level % 2: # 下一层的元素需要从右往左打印,因此先压左子节点入栈,再压右子节点入栈
if cur_node.left:
next_stack.append(cur_node.left)
if cur_node.right:
next_stack.append(cur_node.right)
else:
if cur_node.right:
next_stack.append(cur_node.right)
if cur_node.left:
next_stack.append(cur_node.left)
if not cur_stack: # 这一层的栈空了之后,交换这两个栈
cur_stack, next_stack = next_stack, cur_stack
4. 总结
队列和栈都可以实现这个题,但是选择不同的容器来实现,最后的时间复杂度和空间复杂是不一样的,就这道题而言,明显使用栈来实现的,时间复杂度更低(主要是低在弹出需要打印的元素这一步,队列这一步时间复杂度为O(n), 而栈这一步的时间复杂度为O(1))。
5. 参考文献
[1] 剑指offer丛书