<LeetCode OJ> 144 / 145 / 94 Binary Tree (Pre & In & Post) order Traversal

本文详细介绍了二叉树的三种遍历方式:前序、中序和后序遍历。包括递归与迭代实现方法,并附带了C++代码示例。

144. Binary Tree Preorder Traversal


Total Accepted: 108586  Total Submissions: 278837  Difficulty: Medium

Given a binary tree, return the preorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

   1
    \
     2
    /
   3

return [1,2,3].

Note: Recursive solution is trivial, could you do it iteratively?


1,前序遍历:
递归解法:

基本规则,总是先访问根节点在左节点,在右节点

class Solution {
public:
    vector<int> result;
    vector<int> preorderTraversal(TreeNode* root) {
        if(root){
            result.push_back(root->val);
            preorderTraversal(root->left);
            preorderTraversal(root->right);
        }
        return result;
    }
};

迭代解法:

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        if (root==NULL) 
            return result;  
        stack<TreeNode*> stk;  
        TreeNode* pCurNode=root;  
        stk.push(pCurNode);  
        while (!stk.empty())
        {  
            pCurNode = stk.top();  
            stk.pop();  
            result.push_back(pCurNode->val);  
  
            if (pCurNode->right)  
                stk.push(pCurNode->right); //后压进来的后访问 
            if (pCurNode->left)  
                stk.push(pCurNode->left);  
        }  
        return result;  
    }
private:
  vector<int> result;  
};




94. Binary Tree Inorder Traversal


Total Accepted: 111035  Total Submissions: 286275  Difficulty: Medium

Given a binary tree, return the inorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

   1
    \
     2
    /
   3

return [1,3,2].

Note: Recursive solution is trivial, could you do it iteratively?

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.


2,中序遍历:

递归解法:

总是遍历树的左子,再当前节点,再右子

class Solution {  
public:  
    vector<int> inorderTraversal(TreeNode* root) {  
         if(root){    
            inorderTraversal(root->left);    
            result.push_back(root->val);    
            inorderTraversal(root->right);    
        }    
        return result;    
    }    
private:    
    vector<int> result;   
};  


迭代解法:

class Solution {  
public:  
    vector<int> inorderTraversal(TreeNode* root) {  
        if (root==NULL)     
            return result;      
        stack<TreeNode*> stk;      
        TreeNode* pCurNode=root;      
        while (!stk.empty() ||pCurNode)    
        {      
            while(pCurNode)//先把当前节点的所有左子压进去,  
            {  
                stk.push(pCurNode);  
                pCurNode=pCurNode->left;  
            }  
  
            pCurNode=stk.top();  
            stk.pop();//访问当前节点  
            result.push_back(pCurNode->val);  
              
            pCurNode=pCurNode->right;//再访问当前节点的右子树  
        }      
        return result;      
    }    
private:    
    vector<int> result;      
}; 


综上述:都可以采用栈来实现。将当前节点,左子,右子压进栈的顺序以及访问后的弹出栈形成的访问顺序,目的就是在维护要求的遍历顺序。




145. Binary Tree Postorder Traversal


Total Accepted: 89388  Total Submissions: 257694  Difficulty: Hard

Given a binary tree, return the postorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

   1
    \
     2
    /
   3

return [3,2,1].

Note: Recursive solution is trivial, could you do it iteratively?


3,后序遍历:
总是先访问左子,再右子,最后当前节点
递归解法:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if(root!=NULL)
        {
            postorderTraversal(root->left);
            postorderTraversal(root->right);
            result.push_back(root->val);
        }
        return result;
    }
private:
    vector<int> result;    
};


迭代解法

然而发现回顾了一下也没用,尼玛,尽然要用两个栈或者用到了前后节点来维护。
别人的算法设计:

输出栈:获取最终的输出结果

辅助栈:

1,利用辅助栈总是先将当前节点压进栈,接着弹给输出栈(此时他的顺序已确定,所以最先进输出栈,因为最后访问),

2,再左子进辅助栈,在右子进辅助栈(此时在栈顶,下次循环他已被确定顺序)

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if (root==NULL) 
            return result;  
        stack<TreeNode*> outStk;//辅助栈将维护此栈的顺序就是后序遍历的顺序
        stack<TreeNode*> assistStk;//辅助栈
        TreeNode *pCurNode = root;
        assistStk.push(pCurNode);
        
        while (!assistStk.empty())
        {
            pCurNode = assistStk.top();
            assistStk.pop();
            outStk.push(pCurNode);
            
            if (pCurNode->left!=NULL)
                assistStk.push(pCurNode->left);
            if (pCurNode->right!=NULL)
                assistStk.push(pCurNode->right);
        }
        while (!outStk.empty())
        {
            result.push_back(outStk.top()->val);
            outStk.pop();
        }
        return result;
    }
private:
  vector<int> result;  
};




注:本博文为EbowTang原创,后续可能继续更新本文。如果转载,请务必复制本条信息!

原文地址:http://blog.csdn.net/ebowtang/article/details/50572826

原作者博客:http://blog.csdn.net/ebowtang

下面是该段代码的 **Visual Studio 可运行完整版本**,包含: - `TreeNode` 节点定义 - `buildTree` 函数的完整实现(从前序和中序遍历构造二叉树) - 主函数中测试用例 - 打印构建后的二叉树(前序遍历验证) --- ## ✅ Visual Studio 完整运行代码 ```cpp #include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;algorithm&gt; #include &lt;ranges&gt; using namespace std; // 二叉树节点定义 struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {} }; class Solution { public: TreeNode* buildTree(vector&lt;int&gt;&amp; preorder, vector&lt;int&gt;&amp; inorder) { if (preorder.empty()) { return nullptr; } // 查找根节点在中序遍历中的位置 auto root_it = ranges::find(inorder, preorder[0]); int left_size = distance(inorder.begin(), root_it); // 左子树节点数量 // 划分左子树和右子树的前序和中序序列 vector&lt;int&gt; pre_left(preorder.begin() + 1, preorder.begin() + 1 + left_size); vector&lt;int&gt; pre_right(preorder.begin() + 1 + left_size, preorder.end()); vector&lt;int&gt; in_left(inorder.begin(), inorder.begin() + left_size); vector&lt;int&gt; in_right(inorder.begin() + 1 + left_size, inorder.end()); // 递归构建左右子树 TreeNode* left = buildTree(pre_left, in_left); TreeNode* right = buildTree(pre_right, in_right); return new TreeNode(preorder[0], left, right); } // 前序遍历打印二叉树 void preorderPrint(TreeNode* root) { if (root == nullptr) { cout &lt;&lt; &quot;null &quot;; return; } cout &lt;&lt; root-&gt;val &lt;&lt; &quot; &quot;; preorderPrint(root-&gt;left); preorderPrint(root-&gt;right); } // 析构函数(手动释放内存) void deleteTree(TreeNode* root) { if (root == nullptr) return; deleteTree(root-&gt;left); deleteTree(root-&gt;right); delete root; } }; int main() { Solution sol; // 示例输入 vector&lt;int&gt; preorder = {3, 9, 20, 15, 7}; vector&lt;int&gt; inorder = {9, 3, 15, 20, 7}; // 构建二叉树 TreeNode* root = sol.buildTree(preorder, inorder); // 打印前序遍历结果以验证是否正确 cout &lt;&lt; &quot;构建的二叉树前序遍历结果: &quot;; sol.preorderPrint(root); cout &lt;&lt; endl; // 释放内存 sol.deleteTree(root); return 0; } ``` --- ## 📌 编译与运行说明(适用于 Visual Studio) 1. 打开 Visual Studio 2. 创建一个 **C++ 控制台应用程序(Console Application)** 3. 删除默认生成的代码内容 4. 将上面的代码粘贴到 `.cpp` 文件中(如 `main.cpp`) 5. 确保你的编译器支持 **C++20**,因为使用了 `&lt;ranges&gt;` 和范围查找 - VS 2022 及以上版本支持 C++20 6. 按 `Ctrl + F5` 或点击 **&ldquo;本地 Windows 调试器&rdquo;** 运行程序 --- ## 🧾 输出结果示例 ``` 构建的二叉树前序遍历结果: 3 9 null null 20 15 null null 7 null null ``` 说明构建成功,结构如下: ``` 3 / \ 9 20 / \ 15 7 ``` --- ## 🧠 代码解释 - `preorder[0]` 是当前子树的根节点。 - 在 `inorder` 中找到该根节点,左边就是左子树,右边就是右子树。 - 根据左子树大小,划分 `preorder` 中的左右子树。 - 递归构造左右子树。 - 最后返回构造好的当前子树根节点。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值