二叉树的前序、中序、后序的递归遍历及迭代遍历

本文详细介绍了二叉树的前序、中序、后序遍历,包括递归和迭代两种方法。递归遍历代码简洁易懂,而迭代遍历中,前序和后序遍历利用栈实现,中序遍历则需要用到栈和指针。理解这些遍历方式对于二叉树的学习至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉树的前序、中序、后序的递归遍历及迭代遍历

最近复习二叉树时,又复习到了二叉树的经典问题:前序、中序、后序遍历。所以写这篇blog记录自己的心得体会,也分享出来供大家学习参考。

首先要明确一点,前、中、后序的遍历方式有什么不同:这里前中后,其实指的就是中间节点的遍历顺序,只要大家记住前中后序指的就是中间节点的位置就可以了。

看如下中间节点的顺序,就可以发现,中间节点的顺序就是所谓的遍历方式:

  • 前序遍历:中左右
  • 中序遍历:左中右
  • 后序遍历:左右中

请添加图片描述

下面给大家带来递归的前序、中序、后序遍历方式:

递归前序遍历:

void traversal(TreeNode* root, vector<int>res)
{
    if(root == NULL) return;     //节点为空直接返回
    res.push_back(root -> val);  
    traversal(root -> left); //左节点
    traversal(root -> right);//右节点
}

递归中序遍历:

void traversal(TreeNode* root, vector<int>res)
{
    if(root == NULL) return;     //节点为空直接返回
    traversal(root -> left); //左节点
    res.push_back(root -> val);  //中间节点
    traversal(root -> right);//右节点
}

递归后序遍历:

void traversal(TreeNode* root, vector<int>res)
{
    if(root == NULL) return;     //节点为空直接返回
    traversal(root -> left); //左节点
    traversal(root -> right);//右节点
    res.push_back(root -> val);  //中间节点
}

通过上述三段代码,我们可以发现二叉树的前序、中序、后序遍历代码都十分简洁,且十分相似,只需要改变函数内部语句顺序,就可完成转换。所以递归方法十分简洁易懂,适合初学者记忆

下面来介绍这三种遍历方式的迭代方式:

迭代前序遍历:

vector<int> preorderTraversal(TreeNode* root) {
        vector<int>res;
        if(root == nullptr) return res;
        stack<TreeNode*>stk;//新建一个栈,来存储TreeNode*
        stk.push(root);
        while(!stk.empty())
        {
            TreeNode* cur = stk.top();
            stk.pop();
            res.push_back(cur -> val);
            if(cur -> right)    //因为遍历顺序是中左右,所以最后遍历的右节点要先入栈
            stk.push(cur -> right);
            if(cur -> left)
            stk.push(cur -> left);
        }
        return res;

    }

迭代中序遍历:

vector<int> inorderTraversal(TreeNode* root) {
        vector<int>res;
        stack<TreeNode*>stk;
        if(root == nullptr) return res;
        TreeNode* cur = root;
        while(cur!= nullptr || !stk.empty())
        {
            if(cur != nullptr) // 指针来访问节点,访问到最底层
            {
                stk.push(cur); //将访问到的节点进栈
                cur = cur -> left; // 左
            }
            else
            {
                cur = stk.top(); //弹出数据,放入res中
                stk.pop();
                res.push_back(cur -> val); // 中
                cur = cur -> right; // 右
            }
        }
        return res;

    }

迭代后序遍历:

vector<int> postorderTraversal(TreeNode* root) {
        vector<int>res;
        if(root == nullptr) return res;
        stack<TreeNode*>stk;
        stk.push(root); // 与前序遍历相同
        while(!stk.empty())
        {
            TreeNode* cur = stk.top();
            stk.pop();
            res.push_back(cur -> val);
            if(cur -> left)        //可以先转换为中右左,最后通过reverse转换为后序遍历左右中
            stk.push(cur -> left); //左节点最后遍历,先入栈
            if(cur -> right)
            stk.push(cur -> right);
        }
        reverse(res.begin(), res.end());
        return res;

    }

从上述三段代码,我们可以看出,迭代前序和后序遍历类似,只需用到栈,而中序遍历特殊,不仅用到了还用到了指针,这需要特别注意!

最后,希望这篇文章能给大家带来帮助!

### Java中二叉树前序、中后序遍历方法及实现 #### 一、基本概念 在二叉树遍历过程中,主要涉及三种方式:前序遍历(Pre-order Traversal)、中序遍历(In-order Traversal)以及后序遍历(Post-order Traversal)。每种遍历方式都遵循特定的访问顺[^1]。 - **前序遍历**:按照“根 -> 左子树 -> 右子树”的顺进行访问。 - **中序遍历**:按照“左子树 -> 根 -> 右子树”的顺进行访问。 - **后序遍历**:按照“左子树 -> 右子树 -> 根”的顺进行访问。 #### 二、递归实现 以下是基于递归的方式分别实现前序、中后序遍历的方法: ```java class TreeNode { char val; TreeNode left, right; TreeNode(char item) { val = item; left = right = null; } } public class BinaryTreeTraversal { // 前序遍历 public void preOrder(TreeNode node) { if (node == null) { return; } System.out.print(node.val + " "); // 访问当前节点 preOrder(node.left); // 遍历左子树 preOrder(node.right); // 遍历右子树 } // 中序遍历 public void inOrder(TreeNode node) { if (node == null) { return; } inOrder(node.left); // 遍历左子树 System.out.print(node.val + " "); // 访问当前节点 inOrder(node.right); // 遍历右子树 } // 后序遍历 public void postOrder(TreeNode node) { if (node == null) { return; } postOrder(node.left); // 遍历左子树 postOrder(node.right); // 遍历右子树 System.out.print(node.val + " "); // 访问当前节点 } } ``` 上述代码展示了如何通过递归实现二叉树的三种遍历方式。对于每一个节点,递归调用其左右子树并按指定顺打印节点值[^2]。 #### 三、非递归实现 除了递归之外,还可以利用栈结构来完成这些遍历操作。下面是非递归版本的具体实现: ##### 1. 前序遍历(非递归) ```java import java.util.Stack; public void iterativePreOrder(TreeNode root) { Stack<TreeNode> stack = new Stack<>(); TreeNode current = root; while (current != null || !stack.isEmpty()) { if (current != null) { System.out.print(current.val + " "); stack.push(current); current = current.left; } else { current = stack.pop(); current = current.right; } } } ``` ##### 2. 中序遍历(非递归) ```java import java.util.Stack; public void iterativeInOrder(TreeNode root) { Stack<TreeNode> stack = new Stack<>(); TreeNode current = root; while (current != null || !stack.isEmpty()) { if (current != null) { stack.push(current); current = current.left; } else { current = stack.pop(); System.out.print(current.val + " "); current = current.right; } } } ``` ##### 3. 后序遍历(非递归后序遍历稍微复杂一些,通常需要借助两个栈或者标记已经访问过的节点: ```java import java.util.Stack; public void iterativePostOrder(TreeNode root) { if (root == null) return; Stack<TreeNode> s1 = new Stack<>(); Stack<TreeNode> s2 = new Stack<>(); s1.push(root); while (!s1.isEmpty()) { TreeNode temp = s1.pop(); s2.push(temp); if (temp.left != null) { s1.push(temp.left); } if (temp.right != null) { s1.push(temp.right); } } while (!s2.isEmpty()) { System.out.print(s2.pop().val + " "); } } ``` 以上实现了不依赖于递归的堆栈机制来进行各种类型的遍历[^3]。 --- ### 总结 无论是采用递归还是迭代形式,都可以有效地完成二叉树的不同遍历需求。具体选择取决于实际应用场景和个人偏好。如果追求简洁明了,则推荐使用递归;而当考虑性能优化或避免深层数组溢出风险时,可以尝试非递归方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值