二叉树的遍历是二叉树操作中的基本问题之一,主要有四种遍历方式:前序遍历(Preorder Traversal)、中序遍历(Inorder Traversal)、后序遍历(Postorder Traversal)和层序遍历(Level-Order Traversal,也称为广度优先遍历,前三种也称为深度优先遍历)。以下是用Java实现这些遍历方式的基本方法。
首先,定义二叉树的节点类:
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
1. 前序遍历(Preorder Traversal)
前序遍历的顺序是:根节点 -> 左子树 -> 右子树。
递归实现:
public void preorder(TreeNode root) {
if (root == null) {
return;
}
System.out.print(root.val + " ");
preorder(root.left);
preorder(root.right);
}
非递归(迭代)实现(使用栈):
import java.util.Stack;
public void preorderTraversalIterative(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
System.out.print(node.val + " ");
if (node.right != null) {
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
}
}
// 注意:上述迭代实现为了与递归顺序一致,采用了先右后左的入栈顺序,但这并不是必须的。
// 更常见的做法是直接先左后右入栈,因为栈是后进先出的结构。
}
2. 中序遍历(Inorder Traversal)
中序遍历的顺序是:左子树 -> 根节点 -> 右子树。
递归实现:
public void inorderTraversalRecursive(TreeNode root) {
if (root == null) {
return;
}
inorderTraversalRecursive(root.left);
System.out.print(root.val + " ");
inorderTraversalRecursive(root.right);
}
非递归(迭代)实现(使用栈):
public void inorderTraversalIterative(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
System.out.print(curr.val + " ");
curr = curr.right;
}
}
3. 后序遍历(Postorder Traversal)
后序遍历的顺序是:左子树 -> 右子树 -> 根节点。
递归实现:
public void postorderTraversalRecursive(TreeNode root) {
if (root == null) {
return;
}
postorderTraversalRecursive(root.left);
postorderTraversalRecursive(root.right);
System.out.print(root.val + " ");
}
非递归(迭代)实现(使用栈和标记位,或使用两个栈):
import java.util.Stack;
class NodeWithFlag {
TreeNode node;
boolean isFirstVisit;
NodeWithFlag(TreeNode node, boolean isFirstVisit) {
this.node = node;
this.isFirstVisit = isFirstVisit;
}
}
public void postorderTraversalIterativeWithFlag(TreeNode root) {
if (root == null) {
return;
}
Stack<NodeWithFlag> stack = new Stack<>();
stack.push(new NodeWithFlag(root, true));
while (!stack.isEmpty()) {
NodeWithFlag nodeWithFlag = stack.pop();
TreeNode node = nodeWithFlag.node;
if (nodeWithFlag.isFirstVisit) {
// 第一次访问,先将右子树(如果存在)和左子树(如果存在)压入栈
// 并标记为第一次访问
if (node.right != null) {
stack.push(new NodeWithFlag(node.right, true));
}
if (node.left != null) {
stack.push(new NodeWithFlag(node.left, true));
}
// 然后将当前节点再次压入栈,但标记为第二次访问
stack.push(new NodeWithFlag(node, false));
} else {
// 第二次访问,此时可以访问节点了
System.out.print(node.val + " ");
}
}
}
4. 层序遍历(Level-Order Traversal)
层序遍历的顺序是从上到下、从左到右逐层遍历。
实现(使用队列):
import java.util.LinkedList;
import java.util.Queue;
public class BinaryTreeLevelOrderTraversal {
public void levelOrderTraversal(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root); // 将根节点加入队列
while (!queue.isEmpty()) {
TreeNode currentNode = queue.poll(); // 从队列中取出一个节点
System.out.print(currentNode.val + " "); // 访问该节点
// 如果左子节点不为空,则加入队列
if (currentNode.left != null) {
queue.offer(currentNode.left);
}
// 如果右子节点不为空,则加入队列
if (currentNode.right != null) {
queue.offer(currentNode.right);
}
}
}
public static void main(String[] args) {
// 构造一个简单的二叉树
// 1
// / \
// 2 3
// / \
// 4 5
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
BinaryTreeLevelOrderTraversal bt = new BinaryTreeLevelOrderTraversal();
bt.levelOrderTraversal(root); // 输出应该是 1 2 3 4 5
}
}