二叉树的遍历方式有递归遍历和非递归遍历,其中又有先序遍历,中序遍历,后序遍历。
先序遍历即以“头左右”的顺序,中序遍历以“左头右”的顺序,后序遍历以“左右头”的顺序。
目录
递归遍历
遍历的时候可以发现一个节点遇到过3次,而仔细推敲可以发现:如果每次都在第一次与遇到时处理该节点的顺序就为先序遍历;每次都在第二次与遇到时处理该节点的顺序就为中序遍历;每次都在第三次与遇到时处理该节点的顺序就为后序遍历。
public static void fun(Node head){
if(head==null){
return;
}
//1
fun(head.left);
//2
fun(head.right);
//3
}
所以先序遍历:
public static void fun(Node head){
if(head==null){
return;
}
System.out.println(head.data);
fun(head.left);
fun(head.right);
}
中序遍历:
public static void fun(Node head){
if(head==null){
return;
}
fun(head.left);
System.out.println(head.data);
fun(head.right);
}
后序遍历:
public static void fun(Node head){
if(head==null){
return;
}
fun(head.left);
fun(head.right);
System.out.println(head.data);
}
非递归遍历
先序遍历处理规则可以为:每次从栈中弹出一个节点,之后处理,再将右节点压栈,之后把左节点压栈,最后重复这个过程。可以这么理解:先序遍历的顺序为“头左右”所以入栈顺序可以为“右左头”;
public static void preTraverse(Node head){
if(head==null){
return;
}
Stack<Node> stack=new Stack<Node>();
stack.add(head);
while(!stack.isEmpty()){
head=stack.pop();
System.out.println(head.data);
if(head.right!=null){
stack.push(head.right);
}
if(head.left!=null){
stack.push(head.left);
}
}
}
后序遍历同上规则,只是先将左节点压栈,再将右节点压栈,之后把每次弹出的元素存到另一个栈中,之后统一打印出。
public static void houTraverse(Node head){
if(head==null){
return;
}
Stack<Node> s1=new Stack<Node>();
Stack<Node> s2=new Stack<Node>();
s1.add(head);
while(!s1.isEmpty()){
head=s1.pop();
s2.push(head);
if(head.left!=null){
s1.push(head.left);
}
if(head.right!=null){
s1.push(head.right);
}
}
while (!s2.isEmpty()){
System.out.println(s2.pop().data);
}
}
中序遍历的规则为,每颗子树整棵树的左节点压栈,在弹出的过程中处理,对弹出节点的右节点重复这个过程。建议自己画图去梳理这个过程,不要觉得麻烦。
public static void midTraverse(Node head){
if(head==null) {
return;
}
Stack<Node> stack=new Stack<Node>();
while(!stack.isEmpty()||head!=null){
if(head!=null) {
stack.push(head);
head = head.left;
}else {
head=stack.pop();
System.out.println(head.data);
head=head.right;
}
}
}