代码随想录第14天 | 递归遍历、 迭代遍历、统一迭代

一、前言

参考文献:代码随想录

今天的内容比较简单,主要考察的是二叉树的前序、中序、后序遍历的三种形式的遍历,分别有递归遍历,迭代遍历,统一迭代,三种方式。

二、递归遍历:

1、思路:

使用递归就要想好

(1)返回的是什么

(2)传输什么参数?

(3)终止条件是什么?

(4)主体是什么?

想好这三个基本就可以把递归写出来了,在二叉树的遍历当中,我们传入的当然是根节点了,终止条件便是节点为空了,这样我们就很轻而易举地得到了如下代码。

2、前序遍历代码:

/**
 * 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 {
private:
    void traversal(TreeNode *root, vector<int> &result) {
        // 递归终止条件
        if (root != NULL) {
            result.push_back(root->val);
            traversal(root->left, result);
            traversal(root->right, result);
        }
    }
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

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 {
private: 
        void traversal(TreeNode *root, vector<int> &result) {
        // 递归终止条件
        if (root != NULL) {
            // 左子树
            traversal(root->left, result);
            // 取值
            result.push_back(root->val);
            // 右子树
            traversal(root->right, result);
        }
    }
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

4、后序遍历代码:

后序遍历就不必多说了吧,也是只需要改变一下存数的位置就ok了

/**
 * 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 {
private: 
    void traversal(TreeNode *root, vector<int> &result) {
        // 递归终止条件
    if (root != NULL) {
        // 左子树
        traversal(root->left, result);
        // 右子树
        traversal(root->right, result);
        // 取值
        result.push_back(root->val);
    }
}
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

三、迭代遍历

1、思路:

迭代遍历根据我的理解就是把递归换成了一个while循环再加上栈的辅助就是一个迭代了,用while和栈完成递归需要做的事情。

2、前序遍历代码:

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> my_stack;
        if (root == NULL) return result;
        // 先存入root
        my_stack.push(root);

        while (!my_stack.empty()) {
            // 存数操作,出栈操作
            TreeNode* temp = my_stack.top();
            my_stack.pop();
            result.push_back(temp->val);

            // 这里必须先存如right才可以,因为栈先进后出。
            if (temp->right) my_stack.push(temp->right); // 空节点不如栈
            if (temp->left) my_stack.push(temp->left); // 空节点不如栈
        }
        return result;
    }
};

细节都在代码中,请各位录友友看看咯,首先是先存节点,再存数,然后存右指针,再存左指针。

3、中序遍历代码:

我自己已经忘记了怎么去遍历中序了,看完卡哥的题解后恍然大悟,我总结了以下几点:

1、先设置一个cur遍历到二叉树的最左边(存到stack里面)。

2、到cur==NULL时,就从栈中弹出元素。

3、记录元素,看右子树是否存在。

    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> my_stack;
        if (root == NULL) return result;

        TreeNode* cur = root;
        while (cur != NULL || !my_stack.empty()) {
            // 一直往左边找,边记录,找到最后的叶子节点
            if (cur != NULL) {
                my_stack.push(cur);
                cur = cur->left;
            } else {
                // cur == NULL 就从栈中弹出元素,记录
                cur = my_stack.top();
                my_stack.pop();
                // 记录
                result.push_back(cur->val);
                // 看右指针是否存在,在if上判断,存在right就继续往下遍历了。
                cur = cur->right;
            }
        }
        return result;
    }

4、后序遍历代码:

后续迭代遍历与先序迭代遍历大差不差,只需要把从循环遍历出来的元素顺序变为中右左,然后在反转一下,就OK了。

    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> my_stack;
        if (root == NULL) return result;
        my_stack.push(root);
        
        while (!my_stack.empty()) {
            TreeNode* node = my_stack.top();
            my_stack.pop();

            // 存数
            result.push_back(node->val);      
            // 先插入左元素,因为先进后出
            if (node->left) my_stack.push(node->left);
            // 同理
            if (node->right) my_stack.push(node->right);

        }
        // 先出来的是右元素,所以最终的元素排序就是中右左,所以只要反转一下就OK了
        reverse(result.begin(), result.end());
        
        return result;
    }

四、统一迭代

今天比较累了,还是放过他吧。。

今日学习时间1个半小时。很有收获,初步了解了递归以及其迭代

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值