题目一描述:
从上往下打印二叉树的每个节点,同一层的节点按照从左到右的顺序打印。例如输入下图的二叉树,则一次打印出8,6,10,5,7,9,11。
分析:
这道题实质上考察的就是树的遍历算法,只是这种遍历不是我们熟悉的前序、中序或者后序遍历。由于我们不太熟悉这种按层遍历的方法,可能一下也想不清楚遍历的过程。
因为按层打印的顺序决定应该先打印的根节点,所以我们从树的根节点开始分析。为了接下来能够打印8的节点的两个子节点,我们应该在遍历到该节点时把值为6和10的两个节点保存到一个容器中,现在容器内就有两个节点了。按照从左到右打印的要求,我们先取出值为6的节点。打印出6后把它的值分别为5和7的两个节点放入数据容器。此时数据容器中有三个节点,值分别为10,5,7.接下来我们从数据容器中取出值为10的节点。注意到值为10的节点比值为5,7,的节点先放入容器,此时又比这两个节点先取出,这就是我们通常说的先入先出,因此不难看出这个容器应该是一个队列。由于值为5,7,9,11的节点都没有子节点,因此只要依次打印即可。
通过分析具体例子,我们可以找到从上到下打印二叉树的规律:每一次打印一个节点的时候,如果该节点有子节点,把该节点的子节点放到一个队列的尾。接下来到队列的头部取出最早进入队列的节点,重复前面打印操作,直到队列中所有的节点都被打印出为止。
代码如下:
/**
* 层次遍历
* 从上到下访问节点,当访问到某一层时,从左到右访问
*/
public class Solution {
public void fun(TreeNode root){
if(root == null){
return ;
}
//定义队列
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
//取出队列头部节点
TreeNode tempNode = queue.poll();
System.out.print(tempNode.val+"");
if(tempNode.left != null){
queue.add(tempNode.left);
}
if(tempNode.right != null){
queue.add(tempNode.right);
}
}
}
}
//二叉树节点
class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
题目二描述:
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印 ,每一层打印一行。
分析:
这道题和前面的题类似,也可以使用一个队列来保存将要打印的节点。为了把二叉树的每一行单独打印到一行里,我们需要两个变量:一个变量表示在当前层中还没有打印的节点数;另一个变量表示下一层节点的数目。
代码如下:
/**
* 分行从上到下打印二叉树
*/
public class Solution {
TreeNode flagNode = new TreeNode(-1);
public void fun1(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
//下一层节点的数量
int nextLevel = 0;
//当前层中还没有打印的节点数
int toBePrinted = 1;
while (!queue.isEmpty()) {
TreeNode tempNode = queue.poll();
System.out.print(tempNode.val + " ");
if (tempNode.left != null) {
queue.add(tempNode.left);
nextLevel++;
}
if (tempNode.right != null) {
queue.add(tempNode.right);
nextLevel++;
}
toBePrinted--;
if(toBePrinted == 0){
System.out.println();
toBePrinted = nextLevel;
nextLevel = 0;
}
}
}
public void fun2(TreeNode root) {
if(root == null){
return ;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
queue.add(flagNode);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
System.out.print(node.val + " ");
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
if(queue.peek().val == -1 ){
queue.poll();
System.out.println();
if(!queue.isEmpty()){
queue.add(flagNode);
}
}
}
}
}
题目三描述:
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,即第一行按照从左到右的顺序打印,第二层按照从右到左顺序打印,第三行再按照从左到右的顺序打印,其他以此类推。例如,按之字型打印下图的二叉树结果为:
1
3 2
4 5 6 7
15 14 13 12 11 10 9 8
分析:
按之字形顺序打印二叉树需要两个栈。我们在打印某一行结点时,把下一层的子结点保存到相应的栈里。如果当前打印的是奇数层,则先保存左子结点再保存右子结点到一个栈里;如果当前打印的是偶数层,则先保存右子结点再保存左子结点到第二个栈里。
代码如下:
/**
* 按之字形打印节点
*/
public class Solution {
public void fun(TreeNode root) {
if(root == null){
return ;
}
//子节点的加入为:左->右
Stack<TreeNode> s1 = new Stack<>(); //存储奇数层节点
//子节点的加入为:右->左
Stack<TreeNode> s2 = new Stack<>(); //存储偶数层节点
s1.add(root);
while(!s1.isEmpty() || !s2.isEmpty()){
if(s1.isEmpty() && s2.isEmpty()){ //如果两个栈都为空,则退出循环
break;
}
if(!s1.isEmpty()){
while(!s1.isEmpty()){
TreeNode node = s1.pop();
System.out.print(node.val+" ");
if(node.left != null){
s2.add(node.left);
}
if(node.right != null){
s2.add(node.right);
}
}
System.out.println();
}else{
while(!s2.isEmpty()){
TreeNode node = s2.pop();
System.out.print(node.val+" ");
if(node.right != null){
s1.add(node.right);
}
if(node.left != null){
s1.add(node.left);
}
}
System.out.println();
}
}
}
}