本文欢迎转载,转载前请联系作者,经允许后方可转载。转载后请注明出处,谢谢! http://blog.csdn.net/colton_null 作者:喝酒不骑马 Colton_Null from CSDN
一.先序、中序、后续遍历简介
对于列表结构的数据,我们很容易就能通过for循环遍历它。那么对于树形结构的数据,我们如何遍历它呢?
本文介绍有关二叉树的遍历方法,主要有三种——先序、中序、后续遍历。
1.先序遍历
先序遍历是最好理解的一种遍历方法,可以想象它为顺腾摸瓜,摸到一个节点就直接访问它。那么怎么摸呢?先摸根节点,再摸左节点,最后摸右节点。在摸左右节点的时候,如果子节点还有左或右节点,则还要优先访问左节点,依次类推。即根-左-右。
2.中序遍历
中序遍历是先遍历左节点,再访问根节点,再遍历右节点。即左-根-右。
3.后续遍历
后续遍历为先遍历左节点,再遍历右节点,最终读根节点。即左-右-根。
总结:
- 先序遍历:根-左-右。
- 中序遍历:左-根-右。
- 后序遍历:左-右-根。
二.遍历实践
给定一个二叉树如下图所示。
1.先序遍历过程
先读根节点10,然后访问左节点,左节点存在,则读左节点5。然后继续访问5的左节点,读节点3,然后读节点1。此时,1没有左节点,则访问1的右节点,同样1也没有右节点,则回到节点3。继续访问3的右节点,存在,则读4……
最后结果是:10 5 3 1 4 7 8 15 13 11 20 30
2.中序遍历过程
访问根节点10,先不读10,看10有没有左节点,有则访问5。同样不读节点5,看它有没有左节点……最后访问到节点1。节点1没有左节点,则读根节点即1本身,然后访问它的右节点。发现没有右节点,则回到节点5,读节点5,然后访问它的右节点……。
最后结果是:1 3 4 5 7 8 10 11 13 15 20 30
3.后序遍历过程
访问根节点10,读其左节点,存在,则继续读左节点……最后访问到节点1,继续访问节点1的左节点,不存在,则继续访问节点1的右节点,也不存在,所以最终读取节点1。然后回到节点3,访问其右节点4。同样右节点为树叶,则读取4,回到节点3,读取节点3,然后回到节点5,访问其右节点……
最后结果是:1 4 3 8 7 5 11 13 30 20 15 10
三.递归法实现三种遍历(Java)
节点类的定义
BinaryNode.java
public class BinaryNode {
// 节点元素
private Object element;
// 左节点
private BinaryNode left;
// 右节点
private BinaryNode right;
public Object getElement() {
return element;
}
public void setElement(Object element) {
this.element = element;
}
public BinaryNode getLeft() {
return left;
}
public void setLeft(BinaryNode left) {
this.left = left;
}
public BinaryNode getRight() {
return right;
}
public void setRight(BinaryNode right) {
this.right = right;
}
}
1.先序遍历
/**
* 先序遍历打印二叉树(递归)
*
* @param rootNode
*/
public void printTreeByPreorderTraversal(BinaryNode rootNode) {
// 先输出根节点
System.out.print(rootNode.getElement().toString() + " ");
if (rootNode.getLeft() != null) {
// 访问左节点
printTreeByPreorderTraversal(rootNode.getLeft());
}
if (rootNode.getRight() != null) {
// 再访问右节点
printTreeByPreorderTraversal(rootNode.getRight());
}
}
2.中序遍历
/**
* 中序遍历打印二叉树(递归)
*
* @param rootNode
*/
public void printTreeByInorderTraversal(BinaryNode rootNode) {
if (rootNode.getLeft() != null) {
// 先访问左节点
printTreeByInorderTraversal(rootNode.getLeft());
}
// 输入根节点
System.out.print(rootNode.getElement().toString() + " ");
if (rootNode.getRight() != null) {
// 再访问右节点
printTreeByInorderTraversal(rootNode.getRight());
}
}
3.后序遍历
/**
* 后续遍历打印二叉树(递归)
*
* @param rootNode
*/
public void printTreeByPostorderTraversal(BinaryNode rootNode) {
if (rootNode.getLeft() != null) {
// 先访问左节点
printTreeByPostorderTraversal(rootNode.getLeft());
}
if (rootNode.getRight() != null) {
// 再访问右节点
printTreeByPostorderTraversal(rootNode.getRight());
}
// 输出根节点
System.out.print(rootNode.getElement().toString() + " ");
}
四.非递归法实现三种遍历(Java)
1.先序遍历
用栈,将节点压栈,先访问左节点,访问完左节点后出栈,访问右节点。
/**
* 先序遍历打印二叉树(堆栈)
*
* @param rootNode
*/
public void printTreeByPreorderTraversalStack(BinaryNode rootNode) {
Stack<BinaryNode> stack = new Stack<>();
while (rootNode != null || stack.size() > 0) {
if (rootNode != null) {
stack.push(rootNode);
System.out.print(rootNode.getElement().toString() + " ");
rootNode = rootNode.getLeft();
} else {
rootNode = stack.pop();
rootNode = rootNode.getRight();
}
}
}
2.中序遍历
/**
* 中序遍历打印二叉树(堆栈)
* @param rootNode
*/
public void printTreeByInorderTraversalStack(BinaryNode rootNode) {
Stack<BinaryNode> stack = new Stack<>();
while(rootNode != null || stack.size() > 0) {
if(rootNode != null) {
stack.push(rootNode);
rootNode = rootNode.getLeft();
} else {
rootNode = stack.pop();
System.out.print(rootNode.getElement().toString() + " ");
rootNode = rootNode.getRight();
}
}
}
3.后序遍历
后续遍历麻烦一些。主要难点在于要左右节点都访问完后才能读取根节点。这里用两个栈来完成后序遍历过程。一个栈用于遍历,另一个栈用于记录节点的访问顺序。由于栈先进后出,所以用这种方法(两个栈)需要先记录根节点,然后遍历右节点并记录,最后遍历左节点。
/**
* 后续遍历打印二叉树(堆栈)
* 用两个堆栈实现
*
* @param rootNode
*/
public void printTreeByPostorderTraversalWith2Stacks(BinaryNode rootNode) {
// 用于遍历
Stack<BinaryNode> stack = new Stack<>();
// 用于记录输出的堆栈
Stack<BinaryNode> output = new Stack<>();
while (rootNode != null || stack.size() > 0) {
if (rootNode != null) {
stack.push(rootNode);
output.push(rootNode);
// 先找右节点
rootNode = rootNode.getRight();
} else {
rootNode = stack.pop();
rootNode = rootNode.getLeft();
}
}
while (output.size() > 0) {
System.out.print(output.pop().getElement().toString() + " ");
}
}
以上就是有关先序、中序、后序遍历的方法以及其Java实现。
有关[数据结构与算法]的学习内容已经上传到github,喜欢的朋友可以支持一下。
data-structures-and-algorithm-study-notes-java
站在前人的肩膀上前行,感谢以下博客及文献的支持。
- Java实现二叉树先序,中序,后序遍历
- 《数据结果与算法分析 机械工业出版社》