一、遍历方式
前面文章记录了二叉树的创建,那么二叉树该如何遍历呢?
二叉树的遍历方式有四种,分别是前序、中序、后序遍历和层序遍历。
前、中、后分别表示根节点在前遍历或在中间遍历或在最后遍历,层序遍历就是按每一层的节点遍历。上图中简易二叉树的遍历结果如下:
前序:ABC
中序:BAC
后序:BCA
层序:ABC
二、遍历实现
以 二叉树的创建 中的二叉树为例进行遍历。
前序、中序、后序
二叉树的前序、中序、后序遍历也被称为深度优先遍历。
递归实现
//前序遍历
public static void FirstTraversal(node node){
if(node!=null){
System.out.print(node.data);
FirstTraversal(node.leftchild);
FirstTraversal(node.rightchild);
}
}
//中序遍历
public static void MidTraversal(node node){
if(node!=null){
MidTraversal(node.leftchild);
System.out.print(node.data);
MidTraversal(node.rightchild);
}
}
//后序遍历
public static void PostTraversal(node node){
if(node!=null){
PostTraversal(node.leftchild);
PostTraversal(node.rightchild);
System.out.print(node.data);
}
}
A B D # # E # # C # #
ABDEC
DBEAC
DEBCA
可以看到,遍历方式的不同就是输出语句System.out.print()的位置不同。
非递归实现
前序非递归实现
思路: 先访问根节点(任一个节点),然后再访问左子树和右子树
1. 访问根节点P并入栈,直到左孩子为空
2. 此时取出节点,根据出栈节点去找该节点的右孩子,开始新的遍历
public static void FirstTraversal(node root){
if(root == null)
return;
Stack<node> s = new Stack<node>();
node node = root;
while(node!=null || s.size()>0){
while(node != null){
System.out.print(node.data);
s.push(node);
node = node.leftchild;
}
if(s.size()>0){
node = s.pop();
node = node.rightchild;
}
}
}
中序非递归实现
思路:
1. 首先遍历到左子树最下边,一路保存根节点
2. 当节点P左孩子为空时,说明已经到达左子树最下边,这时出栈访问节点P
3. 如果P没有右孩子,则P的根节点出栈;如果P有右孩子,则进入开始新的遍历
public static void MidTraversal(node root){
if(root == null)
return;
Stack<node> s = new Stack<node>();
node node = root;
while(node!=null || s.size()>0){
while(node != null ){
s.push(node);
node = node.leftchild; //进入左子树
}
if(s.size()>0){
node = s.pop();
System.out.print(node.data);
node = node.rightchild; //进入右子树
}
}
}
后序非递归实现
思路: 按照根节点-右节点-左节点的顺序入栈,再顺序出栈
1. 首先遍历右子树,将根节点和右孩子入栈
2. 右孩子为空则转到左子树继续循环,直到节点为空
3. 栈o记录每个节点入栈顺序(根节点-右节点-左节点),最后出栈的顺序就是左节点-右节点-根节点
public static void PostTraversal(node root) {
if(root == null)
return;
Stack<node> s = new Stack<node>();
Stack<node> o = new Stack<node>(); //存储后序遍历的结果
node node = root;
while(node!=null || s.size()>0){
while(node != null ){
s.push(node);
o.push(node);
node = node.rightchild; //进入右子树
}
if(s.size()>0){
node = s.pop();
node = node.leftchild; //进入左子树
}
}
while(o.size() > 0){
System.out.print(o.pop().data);
}
}
层序
按照二叉树的每一层从左到右顺序输出。
层序遍历又被称为广度优先遍历。
非递归实现
思路:
1. 用队列实现,先将根节点入队列,然后马上出队列并访问根节点
2. 接着将根节点的左右子树依次入队列
3. 循环出列访问直到队列为空
public static void LevelTraversal(node root) {
if(root == null)
return;
Queue<node> q = new LinkedList<node>();
q.add(root);
while(q.size()>0){
node node = q.poll();
System.out.print(node.data);
if(node.leftchild != null){
q.add(node.leftchild);
}
if(node.rightchild != null){
q.add(node.rightchild);
}
}
}