关于二叉树遍历,先序,中序,后序其实都是很简单了。
二叉树通常定义:node
public class Node{
public int value;
public Node left;
public Node right;
public Node(int val){
this.val=val;
}
}
先序遍历web
public void preOrder(Node tree){
if(tree==null)
return;
System.out.println(tree.val);
preOrder(tree.left);
preOrder(tree.right);
}
中序,后序仅仅是语句的交换。很是简单,不给出了。算法
全部递归实现的算法,均可用非递归实现:
思路:
通常将递归转为非递归,不是利用循环就是利用栈。
咱们能够本身申请栈来实现:
步骤以下:
1. 申请一个新的栈,将头节点压入栈
2. 从栈中弹出栈顶节点,记为cur,而后打印cur节点的值,再将节点cur的右孩子压入stack,最后压入left child
3. 不断重复步骤2. 直到栈空,所有过程结束svg
弹出一个结点的时候,若是它有孩子的话!
要压入它的左右孩子节点! 没有就直接弹出post
代码:ui
public void preOrderRecur(Node head){
if(head!=null){
Stack<Node> stack=new Stack<Node>();
stack.push(head); //add也能够,但add是ArrayList或者说List类的方法
while(!stack.empty()){
head=stack.pop();
System.out.println(head.val);
if(head.right!=null){
stack.push(head.right);
}
if(head.left!=null){
stack.push(head.left);
}
}
}
}
这种弹出父结点而后就压入它的左右子节点的作法是最常常用到的技巧! !this
public void inOrderUncur(Node head){
if(head!=null)
return;
Stack<Node> stack=new Stack<Node>();
Node cur=head;
while(!stack.empty()||head!=null){
if(head!null){
stack.push(head);
head=head.left;
}else{
head=stack.pop(); //此时head已经为空了,弹栈
System.out.println(head.val);
head=head.right;//若是head.right为null那么同样会继续pop直到这个head不是null,即它的右节点存在了!
}
}
}
总结这个方法: push到left为空,pop到right不为空! spa
直观的想法:
使用两个栈实现。 压入head节点
第一个栈负责依次 弹出父节点 ,而后压入 左子节点 由右子节点
注意是先左后右的压入,其实由于咱们用了第二个栈
弹出的节点都压入第二个栈! 因此咱们要保证第二个栈弹出的顺序是
后序遍历的顺序,因此按照左先右后的压入第一个栈,那么弹出第二个栈的时候就确定是左边先出,右边后出!
最后咱们只须要依次弹出打印右边的便可code
public void postOrderUnRecur(Node head){
if(head!=null){
Stack<Node> s1=new Stack<Node>();
Stack<Node> s2=new Stack<Node>();
s1.push(head);
while(!s1.empty()){
head=s1.pop();//update
s2.push(head);
if(head.left!=null){
s1.push(head.left);
}
if(head.right!=null){
s2.push(head.right);
}
}
while(!s2.empty()){
System.out.println(s2.pop().val+" ");
}
}
}
还有一种方法,使用一个栈实现后序非递归
它的思想是多设置两个变量h和c 。h表明最近一次弹出并打印的节点
c表明栈顶节点。
而后分3种状况处理。这个算法后续再讨论xml