public class TreeNode {

int data;
TreeNode left;
TreeNode right;
TreeNode(int data){
this.data = data;
}
}


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

public class Solution {

/**
* 首先,树的遍历要求先左后右,其次,这里的pre,in,post都是指根节点的顺序。
* 先序遍历,也就是先根遍历,用引用p遍历每一个节点,每一个循环就是对一个节点的处理,处理的逻辑是如果p不是空,那么
* 它代表了一个子树,因此先打印,然后把p压入栈,接着把p赋值为p.left,下一次循环遍历做字数。这里压栈的目的是到时候
* 可以退回来根据根节点找到右子树。如果p为空,那么说明上一个树没有左子树,那么需要出栈,把p赋值为右子树。
* 循环的条件是p不为空或者stack不为空。
*/
public void preOrderTraverse(TreeNode t){
TreeNode p = t;
Stack<TreeNode> stack = new Stack<>();
while(p != null || !stack.isEmpty()){
if (p != null) {
System.out.print(p.data);
stack.push(p);
p = p.left;
}else {
p = stack.pop().right;
}
}
}

/**
* 中根遍历,还是上面的思路,只是循环体的处理不同,如果p不空,那么需要先把p压栈,以便之后回来遍历根和右子树,
* 赋值p为左子树,然后压栈p。如果为空,说明没有左子树,此时出栈,打印,然后把p赋值为右子树。
*/
public void inOrderTraverse(TreeNode t){
TreeNode p = t;
Stack<TreeNode> stack = new Stack<>();
while(p != null || !stack.isEmpty()){
if (p != null) {
stack.push(p);
p = p.left;
}else {
System.out.print(stack.peek().data);
p = stack.pop().right;
}
}
}

public void preOrder(TreeNode t){
if (t == null) {
return;
}
System.out.print(t.data);
preOrder(t.left);
preOrder(t.right);
}

public void inOrder(TreeNode t){
if (t == null) {
return;
}
inOrder(t.left);
System.out.print(t.data);
inOrder(t.right);
}

public void postOrder(TreeNode t){
if (t == null) {
return;
}
postOrder(t.left);
postOrder(t.right);
System.out.print(t.data);
}

public void layerTraverse(TreeNode t){
Queue<TreeNode> queue = new LinkedList<>();
queue.add(t);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
if (node != null) {
System.out.print(node.data);
queue.add(node.left);
queue.add(node.right);
}
}
}

public int deepth(TreeNode t){
if (t==null) {
return 0;
}else {
return Math.max(deepth(t.left), deepth(t.right)) + 1;
}
}
}