【剑指offer】32、从上往下打印二叉树

题目

(一)从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。

(二)从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层打印到一行。

(三)请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

思路

1、每次打印一个节点的时候,如果该节点有子节点,则把该节点的子节点放到一个队列的末尾。接下来到队列的头部,取出最早进入队列的节点,重复前面的打印操作,直到队列中所有的节点都被打印出来。

2、和题(一)类似,也是准备一个队列来保存将要打印的变量,为了把二叉树的每一行单独打印到一行里,我们需要两个变量:一个变量表示在当前层中还没有打印的节点数,另一个变量表示下一层节点的数目。

3、准备两个栈:对于不同层的结点,一个栈用于正向存储,一个栈用于逆向存储,打印出来就正好是相反方向。

 

 

代码

package myNewSwordOffer;

import java.util.LinkedList;
import java.util.Stack;

public class printFromTopToBottom {
	public static class TreeNode{
		int val;
		TreeNode left;
		TreeNode right;
		
		public TreeNode(int val) {
			this.val = val;
		}
	}
	
	//从上往下层次打印二叉树的数值
	public static void printTree1(TreeNode root) {
		if(root == null) {
			return;
		}
		//申请一个队列
		LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
		//将根节点添加到队列中
		queue.offer(root);
		TreeNode node = null;
		//当队列的大小不为0的时候,
		while(queue.size() != 0) {
			//弹出队列的首元素
			node = queue.poll();
			//打印出该节点的值
			System.out.print(node.val + " ");
			//当该节点的左子节点不为空的时候,将它的左子节点都添加到队列中
			if(node.left != null) {
				queue.offer(node.left);
			}
			//同理,当该节点的右子节点不为空的时候,将它的右子节点都添加到队列中
			if(node.right != null) {
				queue.offer(node.right);
			}
		}
		System.out.println();
	}
	
	
	//分行从上往下打印二叉树
	public static void printTree2(TreeNode root) {
		if (root == null)
            return;
        LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        TreeNode node = null;
        int pCount = 0;      //当前层结点数目
        int nextCount = 1;   //下一层结点数目
        while (!queue.isEmpty()) {
            pCount = nextCount;
            nextCount = 0;
            //打印当前层数字,并计算下一层结点数目
            for (int i = 1; i <= pCount; i++) {
                node = queue.poll();
                System.out.print(node.val + " ");
                if (node.left != null) {
                    queue.offer(node.left);
                    nextCount++;
                }
                if (node.right != null) {
                    queue.offer(node.right);
                    nextCount++;
                }
            }
            System.out.println();
        }
	}
	
	//之字形打印数字
	public static void printTree3(TreeNode root) {
		if (root == null)
            return;
        Stack<TreeNode> stack1 = new Stack<TreeNode>();
        Stack<TreeNode> stack2 = new Stack<TreeNode>();
        TreeNode node = null;
        stack1.push(root);
        while(!stack1.empty() || !stack2.empty()) {
            while(!stack1.empty()) {
                node=stack1.pop();
                System.out.print(node.val + " ");
                if (node.left != null)
                    stack2.push(node.left);
                if (node.right != null)
                    stack2.push(node.right);
            }
            System.out.println();
            while(!stack2.empty()) {
                node=stack2.pop();
                System.out.print(node.val + " ");
                if (node.right != null)
                    stack1.push(node.right);
                if (node.left != null)
                    stack1.push(node.left);
            }
            System.out.println();
        }
	}
	
	public static void test(int testNum, TreeNode root) {
		 System.out.println("=========test"+testNum+"===========");
	     System.out.println("method1:");
	     printTree1(root);
	     System.out.println("method2:");
	     printTree2(root);
	     System.out.println("method3:");
	     printTree3(root);
	}
	
	
	//null
	public static void test1() {
		TreeNode node = null;
		test(1, node);
	}
	
	//单个节点
	public static void test2() {
		TreeNode node = new TreeNode(1);
		test(2, node);
	}
	
	//左斜
	public static void test3() {
		TreeNode node1 = new TreeNode(1);
		TreeNode node2 = new TreeNode(2);
		TreeNode node3 = new TreeNode(3);
		node1.left = node2;
		node2.left = node3;
		test(4, node1);
	}
	
	//右斜
	public static void test4() {
		TreeNode node1 = new TreeNode(1);
		TreeNode node2 = new TreeNode(2);
		TreeNode node3 = new TreeNode(3);
		node1.right = node2;
		node2.right = node3;
		test(4, node1);
	}
	
	//完全二叉树
	public static void test5() {
		TreeNode[] nodes = new TreeNode[15];
		for(int i = 0; i < 15; i++) {
			nodes[i] = new TreeNode(i+1);
		}
		for(int i = 0; i < 7; i++) {
			nodes[i].left = nodes[2*i+1];
			nodes[i].right = nodes[2*i+2];
		}
		test(5, nodes[0]);
	}
	
	public static void main(String[] args) {
		test1();
		test2();
		test3();
		test4();
		test5();
	}
}

小结

1、从上往下遍历二叉树,从本质上来讲就是广度优先遍历二叉树。

2、不管是广度优先遍历有向图还是树,都要用到队列。套路是:

首先,把起始节点(对树而言是根节点)放入队列。

然后,每次从队列的头部取出一个节点,遍历这个节点可以到达的节点(对树而言是子节点)都一次放入队列。

重复该过程,知道队列中的节点全都被遍历为止。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值