二叉树的遍历(traversing binary tree)是指从根结点出发,按照某种次序依次访问二叉树中所有的结点,使得每个结点被访问依次且仅被访问一次。由二叉树的递归定义可知,一个非空的二叉树由根节点、左子树,右子树三部分组成,如果用L、D、R表示遍历左子树,遍历根节点,遍历右子树,则有DLR、LDR、LRD、DRL、RDL、RLD六种遍历方式,如果限定先左后右的规则,则遍历方案减少为3种,即DLR(先序(根)遍历)、LDR(中序(根)遍历)、LRD(后序(根)遍历),再加上按层次从左到右进行遍历,总共有四种经常使用的遍历方案。
下面我们先讲述一下前三种遍历方案。
一 讲解
1 先序遍历二叉树
先序遍历二叉树的定义:
若二叉树为空,则空操作;否则
1)访问根节点。
2)先序遍历根节点的左子树。
3)先序遍历根节点的右子树。
例如,上图中的二叉树,有以下先序遍历序列:
ABCDEFGHI
下面分别给出二叉树的先序遍历二叉树的递归算法:
2 中序遍历二叉树
中序遍历二叉树的定义是:
若二叉树为空,则空操作,否则
1)中序遍历根节点的左子树。
2)访问根节点。
3)中序遍历根节点的右子树。
例如,上图中的二叉树,有以下中序遍历序列:
C D B E A F H G I
3 后序遍历二叉树
后序遍历二叉树的定义是:
若二叉树为空,则空操作,否则
1)后序遍历根节点的左子树。
2)后序遍历根节点的右子树。
3)访问根节点。
例如,上图中的二叉树,有以下后序遍历序列:
D C E B H I G F A
二 代码
注:以下为递归算法的代码实现。
/**
* 二叉树节点
* @author Gyl
* @date 2023/2/5
*/
public class Node {
Object value;
Node leftNode;
Node rightNode;
/**
* 构造函数
*/
public Node(Object value){
this.value = value;
}
/**
* 构造函数
*/
public Node(Object value, Node leftNode, Node rightNode) {
this.value = value;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
", leftNode=" + leftNode +
", rightNode=" + rightNode +
'}';
}
}
/**
* 构建二叉树
* @author Gyl
* @date 2023/2/5
*/
public class BinaryTree {
//节点
private Node node;
public BinaryTree(Node node ) { this.node = node;}
public BinaryTree() {}
/**
* 判断二叉树是否为空,为空返回true
* @return
*/
public boolean isEmpty(){ return node==null;}
/**
* 二叉树前序遍历 根-> 左-> 右
* @param node 二叉树节点
*/
public void preRootTraveral(Node node){
if(node == null){
return;
}
//1、输出根
System.out.print(node.value+" ");
//2、遍历左子树
preRootTraveral(node.leftNode);
//3、遍历右子树
preRootTraveral(node.rightNode);
}
/**
* 二叉树中序遍历 左-> 根-> 右
* @param node 二叉树节点
*/
public void midRootTraveral(Node node){
if(node == null){
return;
}
//1、遍历左子树
midRootTraveral(node.leftNode);
//2、输出根
System.out.print(node.value+" ");
//3、遍历右子树
midRootTraveral(node.rightNode);
}
/**
* 二叉树后序遍历 左-> 右->根
* @param node 二叉树节点
*/
public void postRootTraveral(Node node){
if(node == null){
return;
}
//1、遍历左子树
postRootTraveral(node.leftNode);
//2、遍历右子树
postRootTraveral(node.rightNode);
//3、输出根
System.out.print(node.value+" ");
}
/**
* 获取二叉树内节点个数
* @return
*/
public int size(Node node){
if(node==null){
return 0;
}else {
//1、获取左子树的结点个数
int nl = this.size(node.leftNode);
//2、获取右子树的结点个数
int nr = this.size(node.rightNode);
//3、返回个数
return nl+nr+1;
}
}
}
/**
* 二叉树遍历测试
* @author Gyl
* @date 2023/2/5
*/
public class TestBinaryTree {
public static void main(String[] args) {
//手动创建节点
Node node9 = new Node("I",null,null);
Node node8 = new Node("H",null,null);
Node node7 = new Node("G",node8,node9);
Node node6 = new Node("F",null,node7);
Node node5 = new Node("D",null,null);
Node node4 = new Node("E",null,null);
Node node3 = new Node("C",null,node5);
Node node2 = new Node("B",node3,node4);
Node node1 = new Node("A",node2,node6);
//通过根节点创建一个二叉树对象
BinaryTree bTree=new BinaryTree(node1);
//判断是否为空
System.out.println("是否为空:"+bTree.isEmpty());
//获取节点个数
System.out.println("此二叉树的节点个数为:"+bTree.size(node1));
//前序遍历,递归实现
System.out.println("输出前序遍历:");
bTree.preRootTraveral(node1);
//中序遍历,递归实现
System.out.println();
System.out.println("输出中序遍历:");
bTree.midRootTraveral(node1);
//后序遍历,递归实现
System.out.println();
System.out.println("输出后序遍历:");
bTree.postRootTraveral(node1);
}
}