题目描述:给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问)
样例:
之前,我们已经学习了用非递归的解法解决二叉树的前序遍历,中序遍历,后序遍历。对于这三种深搜的策略,我采用了一种特殊的结构——栈。其实,我在之前也谈过,一般深搜可以用栈解决,而广搜,是可以用队列解决的,二叉树的层次遍历,就是一种典型的广度优先搜索。当然,关于广度优先搜索其实问题远不止层次遍历这么简单,这个以后会细讲。
看图,层次遍历的顺序在逻辑上是比较简单的,逐层遍历就行:ABCDEFG
根据队列先进先出的性质,层次遍历用队列就特别简单了。下面我来介绍两种方法,分别使用一个及两个队列。
方法一:使用两个队列
这个比较简单,设置两个队列cur_list,next_list分别存储当前需处理的层的节点以及下一层的节点,拿这幅图来说
1. 先令cur_list存储根节点A,cur_list = [A]
2. 令cur_list中的节点依次出队列,将出队列的节点所存储的值添加到一个空列表level中,此时,level = [A]
3. 将这个被处理节点(A)的左右孩子(如果有的话)依次添加到next_list中,此时next_list = [B,C]
4. 当cur_list为空时(因为不断有节点处队列),交换cur_list与next_list,同时记录下level的值,令level为空,继续进入下一轮循环,处理下一层节点。
逻辑相当简单,可以轻松写出代码:
""" Definition of TreeNode: class TreeNode: def __init__(self, val): self.val = val self.left, self.right = None, None """ class Solution: """ @param root: The root of binary tree. @return: Level order in a list of lists of integers """ def levelOrder(self, root): result = [] cur_list = [] if root: cur_list = [root] next_list = [] # level用来保存每一层的元素 level = [] # 第一步是按层循环 while len(cur_list) != 0: # 对每一层的所有元素遍历 while len(cur_list) != 0: # 删除队首 temp = cur_list.pop(0) level.append(temp.val) # 将下一层的树节点插入next_list if temp.left: next_list.append(temp.left) if temp.right: next_list.append(temp.right) result.append(level) # 交换两个list cur_list, next_list = next_list, [] level = [] return result # write your code here
一个队列的问题核心在于我不知道这一层到底有几个节点,如果不是输出一个二维矩阵的遍历结果,每一行代表一层的话,这个问题就简单了。
现在怎么解决呢,其实有一种很笨,同时也是很简单的方法,那就是使用两个整型的变量,记录当前层以及下一层的节点个数,这样,我就能知道我需要在这一行输出几个值了。
基本思路还是方法一所给出的,稍微修改一下代码就行
""" Definition of TreeNode: class TreeNode: def __init__(self, val): self.val = val self.left, self.right = None, None """ class Solution: """ @param root: The root of binary tree. @return: Level order in a list of lists of integers """ def levelOrder(self, root): result = [] if root is None: return result cur_list = [root] level = [] # 初始化cur_count = 1,因为已经存了根节点 cur_count, next_count = 1, 0 while len(cur_list) != 0: # 循环条件:当前这一层还没处理完 while cur_count != 0: temp = cur_list.pop(0) level.append(temp.val) cur_count = cur_count - 1 if temp.left: cur_list.append(temp.left) next_count = next_count + 1 if temp.right: cur_list.append(temp.right) next_count = next_count + 1 cur_count = next_count next_count = 0 result.append(level) level = [] return result # write your code here
其中,cur_count代表当前这一层还需处理的节点的个数,而next_count代表下一层的节点数(从0开始,逐步加一得到的)
LintCode上还有一道二叉树层次遍历的题目,和这道题基本一样,不同之处在于,要求从底至顶输出,我的理解,实就是把上边的结果在二维数组内做一个翻转罢了,很简单。如果读者对从底至顶的层次遍历所要考察的知识点有不同的的认识,希望可以告诉我其。