创建TreeNode类:
package com.atguigu.binarytree;
public class TreeNode {
public int val; //值
public TreeNode left; //左孩子
public TreeNode right; //右孩子
//构造器
//1.叶子节点的构造
public TreeNode(int val){
this.val = val;
}
//2.非叶子节点的构造
public TreeNode( TreeNode left, int val,TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
@Override
public String toString(){return String.valueOf(this.val);}
}
创建 TreeTravel类:递归方法
package com.atguigu.binarytree;
public class TreeTraversal {
//递归方法遍历
//1.前序遍历:先访问该节点的值,然后前序遍历左子树,最后前序遍历右子树
static void preorder(TreeNode node) {
//传递到最里面并返回到上一级的条件
//每一级又都遵循这个规则:打印值,左子树,右子树
if (node == null) {
return;
}
System.out.print(node.val + "\t");//值
//访问左子树(左子树用左孩子表示)
preorder(node.left);//左
preorder(node.right);//右
}
//2.中序遍历:先中序遍历左子树,然后是访问该节点的值,最后中序遍历右子树
static void Inorder(TreeNode node) {
if (node == null) {
return;
}
Inorder(node.left);//左
System.out.print(node.val + "\t");//值
Inorder(node.right);//右
}
//3.后序遍历:先后序遍历左子树,然后是后序遍历右子树,最后访问该节点的值
static void postorder(TreeNode node) {
if (node == null) {
return;
}
postorder(node.left);//左
postorder(node.right);//右
System.out.print(node.val + "\t");//值
}
}
创建TreeTravel2类:非递归方法
package com.atguigu.binarytree;
import java.util.LinkedList;
public class TreeTraveral2 {
/*
非递归方法:利用一路往左走到底——再回头——往右走的路径不变的规律,
变的是取路口的值的时机:
前序遍历是取 来时 经过路口的值,
中序遍历是取 回时 经过的路口的值。
用栈来模拟回去时的路径,利用栈的先进后出原理
后序遍历:区别于前中序遍历的地方是:
弹栈要处理完右子树才能弹,不是回来时就立刻弹栈,
即弹栈的条件为:1.栈顶元素的右子树为null(叶子结点)2.临时变量记住最近一次弹栈的元素,
若最近一次弹栈的元素与栈顶元素的右孩子相同即当前栈顶元素的右子树已经处理完成(非叶子节点)。
*/
//前序遍历:进栈打印(来时的路取值)
static void Pretraveral(TreeNode node){
LinkedList <TreeNode> stack = new LinkedList<>();//创建栈
TreeNode curr = node; //代表当前节点
while(curr!=null || !stack.isEmpty()){
if(curr!=null){
System.out.print(curr.val+ "\t");
stack.push(curr); //进栈,为了记住回来的路
curr = curr.left; //取左孩子
}else{
TreeNode pop = stack.pop(); //出栈
curr = pop.right; //取右孩子
}
}
}
//中序遍历:出栈打印(来时的路取值)
static void Intraveral(TreeNode node){
LinkedList <TreeNode> stack = new LinkedList<>();//创建栈
TreeNode curr = node; //代表当前节点
while(curr!=null || !stack.isEmpty()){
if(curr!=null){
stack.push(curr); //进栈
curr = curr.left; //取左孩子
}else{
TreeNode pop = stack.pop(); //出栈
System.out.print(pop.val+ "\t");
curr = pop.right; //取右孩子
}
}
}
//后序遍历:
static void posttraveral(TreeNode node){
LinkedList <TreeNode> stack = new LinkedList<>();//创建栈
TreeNode curr = node; //代表当前节点
TreeNode pop = null; //最近一次弹栈的元素
while(curr!=null || !stack.isEmpty()){
if(curr!=null){
stack.push(curr); //进栈
curr = curr.left; //取左孩子
}else{
TreeNode peek = stack.peek();//栈顶元素
if(peek.right == null || peek.right == pop){ //右子树处理完成
pop = stack.pop(); //出栈
System.out.print(pop.val+ "\t");
}else{
curr = peek.right; //处理右孩子
}
}
}
}
/*
合并:基于后序遍历改动
*/
static void traveral(TreeNode node){
LinkedList <TreeNode> stack = new LinkedList<>();//创建栈
TreeNode curr = node; //代表当前节点
TreeNode pop = null; //临时变量:最近一次弹栈的元素
while(curr!=null || !stack.isEmpty()){
if(curr!=null){
stack.push(curr); //进栈
//待处理左子树
System.out.println("前: " + curr.val); //前序遍历 打印值
curr = curr.left;
}else{
TreeNode peek = stack.peek();//栈顶元素
//没有右子树
if(peek.right == null ){
System.out.println("中: " +peek.val);//中序遍历 打印值
pop = stack.pop(); //出栈
System.out.println("后: " +pop.val);//后序遍历 打印值
//右子树处理完成
}else if(peek.right == pop){
pop = stack.pop(); //出栈
System.out.println("后: " +pop.val);//后序遍历 打印值
//待处理右子树
}else{
System.out.println("中: " +peek.val);//中序遍历 打印值
curr = peek.right;
}
}
}
}
}
创建Test测试类
package com.atguigu.binarytree;
import static com.atguigu.binarytree.TreeTraveral2.*;
import static com.atguigu.binarytree.TreeTraversal.*;
public class TreeTest {
public static void main(String[] args) {
TreeNode root = new TreeNode(new TreeNode(new TreeNode(4),2,new TreeNode(7)),
1,new TreeNode(new TreeNode(5),3,new TreeNode(6)));
preorder(root);//1 2 4 7 3 5 6
Inorder(root);//4 2 7 1 5 3 6
postorder(root);//4 7 2 5 6 3 1
Pretraveral(root);//1 2 4 7 3 5 6
Intraveral(root); //4 2 7 1 5 3 6
posttraveral(root); //4 7 2 5 6 3 1
traveral(root);
/*前: 1 前: 2 前: 4 中: 4 后: 4 中: 2 前: 7
中: 7 后: 7 后: 2 中: 1 前: 3 前: 5 中: 5
后: 5 中: 3 前: 6 中: 6 后: 6 后: 3 后: 1*/
}
}