剑指offer_把二叉树打印成多行+之字形

/*
1. 从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

按层次打印可以用队列,如何保证一层输出一行,
进队列的时候,加标记,出队时候遇到标记则一行结束

剑指offer思路:
用两个变量表示当前层还未打印的节点数和下一层的节点数
*/
import java.util.ArrayList;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Stack;

class  Print
{
	public static  ArrayList<ArrayList<Integer>> print1(TreeNode pRoot) {
		ArrayList<ArrayList<Integer>> alAllLine=new ArrayList<ArrayList<Integer>>();

		if (pRoot==null)
		{
			return alAllLine;
		}
		
		ArrayList<Integer> alOneLine=new ArrayList<Integer>();
		alOneLine.add(pRoot.val);
		alAllLine.add(alOneLine);

		Queue<TreeNode> queue=new ArrayDeque<TreeNode>();
		
		queue.add(pRoot.left);
		queue.add(pRoot.right);
		queue.add(pRoot);//pRoot作为标记
		
		ArrayList<Integer> alOneLineNext=new ArrayList<Integer>();
		while (!queue.isEmpty())
		{
			TreeNode front=queue.remove();
			if (front==pRoot)
			{
				alAllLine.add(alOneLineNext);
				if(queue.size()>0)
				{
					alOneLineNext=new ArrayList<Integer>();
					queue.add(pRoot);
				}
				continue;
			}
			alOneLineNext.add(front.val);

			if (front.left!=null)
			{
				queue.add(front.left);
			}
			if (front.right!=null)
			{
				queue.add(front.right);
			}
		}

		return alAllLine;
    }

	public static ArrayList<ArrayList<Integer>> print2(TreeNode pRoot){
		ArrayList<ArrayList<Integer>> alAllLine=new ArrayList<ArrayList<Integer>>();

		if (pRoot==null)
		{
			return alAllLine;
		}
		
		int toBePrinted=1;
		int nextLine=0;

		Queue<TreeNode> queue=new ArrayDeque<TreeNode>();
		queue.add(pRoot);
		
		ArrayList<Integer> alOneLine=new ArrayList<Integer>();
		while (!queue.isEmpty())
		{
			TreeNode front=queue.remove();
			alOneLine.add(front.val);
			toBePrinted--;
			
			if (front.left!=null)
			{
				queue.add(front.left);
				nextLine++;
			}
			if (front.right!=null)
			{
				queue.add(front.right);
				nextLine++;
			}

			if (toBePrinted==0)
			{
				alAllLine.add(alOneLine);
				alOneLine=new ArrayList<Integer>();
				toBePrinted=nextLine;
				nextLine=0;
			}
		}

		return alAllLine;
	}

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

	   如何做到之字,需要栈吗?
	*/
	public static  ArrayList<ArrayList<Integer>> printZ(TreeNode pRoot)
	{
		ArrayList<ArrayList<Integer>> alAllLine=new ArrayList<ArrayList<Integer>>();

		if (pRoot==null)
		{
			return alAllLine;
		}
		
		int toBePrinted=1;
		int nextLine=0;
		int direct=0;

		Queue<TreeNode> queue=new ArrayDeque<TreeNode>();
		queue.add(pRoot);
		
		ArrayList<Integer> alOneLine=new ArrayList<Integer>();
		while (!queue.isEmpty())
		{
			TreeNode front=queue.remove();
			alOneLine.add(front.val);
			toBePrinted--;
			
			if (front.left!=null)
			{
				queue.add(front.left);
				nextLine++;
			}
			if (front.right!=null)
			{
				queue.add(front.right);
				nextLine++;
			}

			if (toBePrinted==0)
			{
				if (direct==0)
				{
					alAllLine.add(alOneLine);
					
				}else	//每隔一层进行反转
				{
					ArrayList<Integer> alOneLineReverse=new ArrayList<Integer>();
					for (int i=alOneLine.size()-1; i>=0; i--)
					{
						alOneLineReverse.add(alOneLine.get(i));
					}
					alAllLine.add(alOneLineReverse);
				}

				direct=1-direct;
				alOneLine=new ArrayList<Integer>();
				toBePrinted=nextLine;
				nextLine=0;
			}
		}

		return alAllLine;
	}

	/*
	上述方法还是用队列按层次遍历,不过是隔一层利用辅助ArrayList反转一下元素顺序
	考虑用栈,直接在遍历过程中确定好元素顺序
	要用两个栈,一个栈用来入,一个用来出,如果只用一个,栈后进先出,元素顺序会打乱
	*/
	public static  ArrayList<ArrayList<Integer>> printZ2(TreeNode pRoot)
	{
		ArrayList<ArrayList<Integer>> alAllLine=new ArrayList<ArrayList<Integer>>();

		if (pRoot==null)
		{
			return alAllLine;
		}
		
		Stack<TreeNode> s1=new Stack<TreeNode>();
		Stack<TreeNode> s2=new Stack<TreeNode>();
		
		s1.push(pRoot);
		while (!s1.empty()||!s2.empty())
		{
			ArrayList<Integer> alOneLine=new ArrayList<Integer>();
			while (!s1.empty())
			{
				TreeNode top=s1.pop();
				alOneLine.add(top.val);

				if (top.left!=null)
				{
					s2.push(top.left);
				}
				if (top.right!=null)
				{
					s2.push(top.right);
				}
			}
			if (alOneLine.size()>0)
			{
				alAllLine.add(alOneLine);
			}
		
			alOneLine=new ArrayList<Integer>();
			while (!s2.empty())
			{
				TreeNode top=s2.pop();
				alOneLine.add(top.val);

				if (top.right!=null)
				{
					s1.push(top.right);
				}
				if (top.left!=null)
				{
					s1.push(top.left);
				}
			}
			if (alOneLine.size()>0)
			{
				alAllLine.add(alOneLine);
			}
		}

		return alAllLine;
	}

	public static void main(String[] args) 
	{
		TreeNode node1=new TreeNode(1);
		TreeNode node2=new TreeNode(2);
		TreeNode node3=new TreeNode(3);
		TreeNode node4=new TreeNode(4);
		TreeNode node5=new TreeNode(5);
		TreeNode node6=new TreeNode(6);
		TreeNode node7=new TreeNode(7);
		
		node1.left=node2;
		node1.right=node3;
		node2.left=node4;
		node2.right=node5;
		node3.left=node6;
		node3.right=node7;
		
		ArrayList<ArrayList<Integer>> alAllLine=printZ2(node1);

		for (ArrayList<Integer> alOneLine: alAllLine)
		{
			for (int i: alOneLine)
			{
				System.out.print(i);
			}
			System.out.println();
		}
		
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值