遍历是数据结构中的常见操作,就是把所有的元素遍历一遍。
线性结构的遍历无非是两种,正序遍历和逆序遍历,也就是从头依次遍历或者从尾依次遍历。
二叉树的遍历方式有 4 种,是根据不同的节点访问顺序来区分:
遍历方法 | 访问顺序 | 备注 |
---|---|---|
前序遍历(Preorder Traversal) | 根节点、左子树、右子树 | |
中序遍历(Inorder Traversal) | 左子树、根节点、右子树 | |
后序遍历(Postorder Traversal) | 左子树、右子树、根节点 | |
层序遍历(Level Order Traversal) | 从上到下、从左到右依次访问每一个节点 |
从上面表格中可以大致总结出前三种遍历的唯一区别就是访问的顺序不同,那么就可以都使用递归的方式实现。
凡是使用递归方式,必须要确定一个结束递归的条件,因为二叉树的遍历都是从根节点开始,直到所有节点都遍历完成,所以结束递归的条件就是节点为 null。
// 结束递归条件
if (node == null) return;
前序遍历
前序遍历的顺序是根节点、左子树,最后右子树
/**
* 前序遍历(递归)
*/
public void preorderTanversal() {
preorderTanversal(root, visitor);
}
private void preorderTanversal(Node<E> node) {
// 结束条件
if (node == null) return;
// 访问根节点
System.out.println(node.element);
// 访问左子树
preorderTanversal(node.left, visitor);
// 访问右子树
preorderTanversal(node.right, visitor);
}
中序遍历
中序遍历的顺序是左子树、根节点,最后右子树
/**
* 中序遍历(递归)
*/
public void inorderTraversal() {
preorderTanversal(root, visitor);
}
private void inorderTraversal(Node<E> node) {
// 结束条件
if (node == null) return;
// 访问左子树
inorderTraversal(node.left, visitor);
// 访问根节点
System.out.println(node.element);
// 访问右子树
inorderTraversal(node.right, visitor);
}
特别:中序遍历是只要保证根节点是在中间访问,那么先访问左子树还是先访问右子树,根据心情来决定就好。
后序遍历
后序遍历的顺序是左子树、右子树,最后是根节点:
/**
* 后序遍历(递归)
*/
public void postorderTraversal() {
preorderTanversal(root, visitor);
}
private void postorderTraversal(Node<E> node) {
// 结束条件
if (node == null) return;
// 访问左子树
postorderTraversal(node.left, visitor);
// 访问右子树
postorderTraversal(node.right, visitor);
// 访问根节点
System.out.println(node.element);
}
层序遍历
层序遍历的访问顺序是从左到右,从上到下依次遍历。那么就可以通过队列的方式去实现,在遍历每一个节点的同时(出队操作),将它的左右子节点依次入队,直到队列中的元素为空,则遍历就结束了。
/**
* 层序遍历
*/
public void leverOrderTraversal() {
if (root == null) return;
// 创建队列
Queue<Node<E>> queue = new LinkedList<>();
// 第一节点入队
queue.offer(root);
while (!queue.isEmpty()) {
// 处理事件
Node<E> node = queue.poll();
System.out.println(node.element);
// 依次将存在的左右子树入队
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
扩展
使用递归方式实现二叉树的遍历在代码实现上是简单的,关键要明白递归的思想和思路。建议在纸上去亲自演算一下递归方式,会有利于理解。