/*
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();
}
}
}
剑指offer_把二叉树打印成多行+之字形
最新推荐文章于 2020-04-07 20:01:08 发布