package binaryTree;
import java.util.Stack;
/**
* @Description: 遍历二叉树,前序、中序、后序
* 每种排序都有两钟实现方式:递归、非递归
* 非递归:用栈来保存先前走过的路径,以即可以在访问子树后,能够利用栈中的信息,回退到当前节点的双亲节点,进行下一步操做
* @Author: hw
* @Date: 2019/8/30 17:50
*/
public class BinaryTreeSelect {
public static void main(String[] args) {
//1. 初始化一棵二叉树:[0,1,2,3,4,5,6,7,8,9]
TreeNode[] node = new TreeNode[10];//以数组形式生成一棵彻底二叉树
for (int i = 0; i <10 ; i++) {
node[i] = new TreeNode(i);
}
for (int i = 0; i <10 ; i++) {
if (i*2+1<10)
node[i].left = node[i*2+1];
if (i*2+2<10)
node[i].right = node[i*2+2];
}
//2. 函数调用
System.out.println("=========前序================");
preOrderRe(node[0]);//前序递归
System.out.println();
preOrder(node[0]);//前序非递归
System.out.println();
System.out.println("=========中序================");
midOrderRe(node[0]);//中序递归
System.out.println();
midOrder(node[0]);//中序非递归
System.out.println();
System.out.println("=========后序================");
postOrderRe(node[0]);//后序递归
System.out.println();
//postOrder(node[0]);//后序非递归
postOrder(node[0]);
}
/**
* 前序:递归
* @param tree
*/
public static void preOrderRe(TreeNode tree){
System.out.print(tree.val);
TreeNode leftTree = tree.left;
if (leftTree != null)
preOrderRe(leftTree);
TreeNode rightTree = tree.right;
if (rightTree != null)
preOrderRe(rightTree);
}
/**
* 前序:非递归
* @param tree
*/
public static void preOrder(TreeNode tree){
Stack stack = new Stack<>();
while (tree!=null || !stack.isEmpty()){
while (tree!=null){
System.out.print(tree.val);
stack.push(tree);
tree = tree.left;
}
if (! stack.isEmpty()){
tree = stack.pop();
tree = tree.right;
}
}
}
/**
* 中序:递归
* @param tree
*/
public static void midOrderRe(TreeNode tree){
if (tree == null)
return;
else {
midOrderRe(tree.left);
System.out.print(tree.val);
midOrderRe(tree.right);
}
}
/**
* 中序:非递归
* @param tree
*/
public static void midOrder(TreeNode tree){
Stack stack = new Stack<>();
while (tree != null || !stack.isEmpty()){
//遍历到最左节点
while(tree != null){
stack.push(tree);
tree = tree.left;
}
if (!stack.isEmpty()){
tree = stack.pop();
System.out.print(tree.val);
tree = tree.right;
}
}
}
/**
* 后序:递归
* @param tree
*/
public static void postOrderRe(TreeNode tree){
if (tree == null){
return;
}
else{
postOrderRe(tree.left);
postOrderRe(tree.right);
System.out.print(tree.val);
}
}
/**
* 后序:非递归
* 利用栈回退时,并不知道是从左子树回退到根节点,仍是从右子树回退到根节点
* 若从左子树回退,则访问右子树;若从右子树回退,则访问根节点
* 因此须要一个辅助栈,记录压栈时是左子树仍是右子树
* @param tree
*/
public static void postOrder(TreeNode tree){
int left =1;//辅助栈里表示左节点
int right=2;//辅助栈里表示右节点
Stack stack = new Stack<>();
Stack stackAssist = new Stack<>();//辅助栈
while (tree != null || !stack.empty()){
//将节点压入栈1,并在辅助栈将节点标记为左节点
while (tree != null){
stack.push(tree);
stackAssist.push(left);
tree=tree.left;
}
//若是是从右子节点返回父节点,则任务完成,将两个栈的栈顶弹出
while (!stack.empty() && stackAssist.peek()==right){
stackAssist.pop();
System.out.print(stack.pop().val);
}
//若是是从左子节点返回父节点,则将标记改成右节点
if (!stack.empty() && stackAssist.peek()==left){
stackAssist.pop();
stackAssist.push(right);
tree=stack.peek().right;
}
}
}
}