二叉树的遍历

二叉树的遍历是二叉树操作中的基本问题之一,主要有四种遍历方式:前序遍历(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  
    }  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没出过地球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值