二叉树01(leetcode144,145,94)

文章详细介绍了二叉树的前序、中序和后序遍历的递归以及迭代实现方法,包括如何利用栈来模拟遍历过程。还提供了统一的迭代法,使代码更易维护和扩展。
摘要由CSDN通过智能技术生成

参考资料:

https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8%BF%AD%E4%BB%A3%E9%81%8D%E5%8E%86.html#%E6%80%9D%E8%B7%AF

144. 二叉树的前序遍历

递归法:

        1. 确定递归函数的参数和返回值。(可以在写的过程补充)

        2. 确定终止条件

        3. 确定单层递归的逻辑

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     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:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root,result);
        return result;

    }
    void traversal(TreeNode* node,vector<int> &vec){
        if(node==nullptr) return;
        vec.push_back(node->val);
        traversal(node->left,vec);
        traversal(node->right,vec);
    }
};

中序遍历(94. 二叉树的中序遍历)、后序遍历(145. 二叉树的后序遍历)  

思路同上,只需更改递归函数的单层递归逻辑顺序即可。

迭代法:

一)前序遍历

        节点访问顺序和处理顺序相同(先访问根节点,先处理根节点)

        对节点的处理:将值存入result数组,将右结点、左节点入栈

//迭代法
    vector<int> preorderTraversal(TreeNode* root){
        vector<int> result;
        if(root==nullptr) return result;
        stack<TreeNode*> stk;
        stk.push(root);//中
        while(!stk.empty()){
            TreeNode* temp=stk.top();
            stk.pop();
            if(temp->right!=nullptr) stk.push(temp->right);//右
            if(temp->left!=nullptr) stk.push(temp->left);//左
            result.push_back(temp->val);
        }
        return result;
    }

一)后序遍历

        1. 将左右节点入栈顺序调转,此时变为“中右左”

        2. 将result数组整个反转reverse

//迭代法(在前序基础上改)
            vector<int> result;
            if(root==nullptr) return result;
            stack<TreeNode*> stk;
            stk.push(root);//中
            while(!stk.empty()){
                TreeNode* temp=stk.top();
                stk.pop();
                //左右顺序调换
                if(temp->left!=nullptr) stk.push(temp->left);//左
                if(temp->right!=nullptr) stk.push(temp->right);//右
                result.push_back(temp->val);
            }//此时数组里面 中右左
            //翻转数组
            reverse(result.begin(),result.end());
            return result;

三)中序遍历

        注意:由于中序遍历里,节点访问顺序与节点处理顺序不同。在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。

//迭代法
        vector<int> vec;
        stack<TreeNode*> stk;
        TreeNode *cur=root;
        while(cur!=nullptr || !stk.empty()){
            if(cur!=nullptr){
                stk.push(cur);//左
                cur=cur->left;
            }
            else{
                cur=stk.top();
                stk.pop();
                vec.push_back(cur->val);//中
                cur=cur->right;//右
            }
        }
        return vec;

统一迭代法:

        上面的迭代法中前中后序遍历的写法不统一,这里进行统一改造使其写法统一。

        方法:待处理结点入栈后统一加入null节点,则在出栈时遇到Null节点就知道下一个节点待处理了。

        //中序遍历
        //空节点标记待处理的节点
        stack<TreeNode*> stk;
        vector<int> result;
        if(root!=nullptr) stk.push(root);
        while(!stk.empty()){
            TreeNode* temp=stk.top();
            if(temp!=nullptr){
                stk.pop();
                //入栈:右中左
                if(temp->right) stk.push(temp->right);
                stk.push(temp);
                stk.push(nullptr);
                if(temp->left) stk.push(temp->left);

            }
            else{//空节点,下一节点待处理
                stk.pop();
                temp=stk.top(); //取出待处理的节点
                stk.pop();
                result.push_back(temp->val);

            }
        }
        return result;

前序、后序操作仅需要更改元素入栈顺序即可 

//前序遍历
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                if (node->right) st.push(node->right);  // 右
                if (node->left) st.push(node->left);    // 左
                st.push(node);                          // 中
                st.push(NULL);
            } else {
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
};

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值