c++二叉树遍历-从递归法到迭代法的前世今生

本文详细介绍了二叉树的前序遍历从递归到迭代的转换过程,通过模拟系统栈来理解迭代法。文章提供了C++代码实现,并展示了如何通过迭代法统一处理前中后序遍历。此外,还强调了算法学习应注重理解和思考,鼓励读者积极探讨。

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

写这个博客的起因

最开始写算法就是为了刷题而刷题, 最终刷完一遍之后忘记得差不多了, 现在写些算法完全是觉得有趣。
前几天写了个c++ 二叉树遍历for loop统一迭代法
觉得写的还不错, 后面想了想,这递归到迭代到底是如何演变过来的了
本文是模拟系统栈递归调用实现的,从他的实现你可以看到通用的迭代法的影子;
talk is cheap, here is the code!

二叉树的定义

using VALUE_TYPE  = int;
struct TreeNode {
    explicit TreeNode(const VALUE_TYPE &val, TreeNode *left = nullptr, TreeNode *right = nullptr) : val(val),
                                                                                                    left(left),
                                                                                                    right(right) {}
    VALUE_TYPE val{};
    struct TreeNode *left{}, *right{};

};

前序遍历递归代码

class Solution {
public:
    void preorderTraversal_recursion_helper(TreeNode *currentFrame, vector<int> &data) {
        if (nullptr == currentFrame) {
            return;
        }
        // 当前frame还未添加到data
        data.push_back(currentFrame->val); // 0
        // currentFrame 入栈位置, 这里的栈值的系统栈, 我们自己用栈模拟的时候需要用栈实际操作
        preorderTraversal_recursion_helper(currentFrame->left, data); // 1
        preorderTraversal_recursion_helper(currentFrame->right, data); // 2
        // 3
        // currentFrame 出栈位置
    }

    vector<int> preorderTraversal_recursion(TreeNode *root) {
        vector<int> ans;
        preorderTraversal_recursion_helper(root, ans);
        return ans;
    }

第一代模拟代码,前序遍历递归—> 用栈迭代

说明:

  1. Item 代表的是一个节点的状态
    t = 0, 节点还未访问过
    t = 1, 节点的左节点还未访问过
    t = 3 节点的右节点还未被访问过
  2. 读迭代法代码的时候请和递归法对照着看
class Solution {
public:
    void preorderTraversal_recursion_helper(TreeNode *root, vector<int> &data) {
        if (nullptr == root) {
            return;
        }
        data.push_back(root->val);  // 0
        // 入栈
        preorderTraversal_recursion_helper(root->left, data); // 1
        preorderTraversal_recursion_helper(root->right, data); // 2
        // 出栈 // 3
    }

    vector<int> preorderTraversal_recursion(TreeNode *root) {
        vector<int> ans;
        preorderTraversal_recursion_helper(root, ans);
        return ans;
    }

    struct Item {
        // t = 0 入栈的状态
        // t = 1 第一次访问
        // t = 2 第二次访问
        // t = 3 第三次访问
        int t{};
        TreeNode *node;
    };

    vector<int> preorderTraversal_stack(TreeNode *root) {
        vector<int> ans;
        if (nullptr == root) {
            return ans;
        }
        stack<Item> st;
        Item cur{0, root};
        //add(st, ans, root);
        while (cur.node || !st.empty()) {
            if (!cur.node) {
                cur = st.top();
                st.pop();
            }
            if (0 == cur.t) {   // 0
                ans.push_back(cur.node->val);
            }
            ++cur.t;
            if (1 == cur.t) {
                // 还不能出栈, 修改完状态重新入栈
                if (cur.node->left) { // 1
                    Item item{.t = 0, cur.node->left};
                    st.push(cur);
                    cur = item;
                }
                continue;
            }
            if (2 == cur.t) {
                if (cur.node->right) { // 2
                    Item item{.t = 0, cur.node->right};
                    st.push(cur);
                    cur = item;
                }
                continue;
            }
            if (3 == cur.t) { // 3
                cur.node = nullptr;
                continue;
            }
        }
        return ans;
    }
};

最终代码 前中后序代码的统一迭代法

enum Order{
    Pre_Order = 0,
    In_Order = 1,
    Post_Order = 2
};

class Solution {
public:
    constexpr static TreeNode* TreeNode::*next_child[3] = {&TreeNode::left, &TreeNode::right, nullptr};
    struct Frame {
        TreeNode *node;
        int t;

        explicit Frame(TreeNode* node = nullptr, int t = -1) :node(node), t(t){}

        TreeNode* TreeNode::* getNextChild() {
            t++;
            if (t > 2) {
                t = 2;
            }
            return next_child[t];
        }
    };

    vector<int> traversal_simulate_stack(TreeNode *root, Order order = Pre_Order) {
        vector<int> ans;
        if (nullptr == root) {
            return ans;
        }
        stack<Frame> st;
        Frame currentFrame{root};
        while (currentFrame.node || !st.empty()) {
            if (!currentFrame.node) {
                currentFrame = st.top();
                st.pop();
            }
            auto child = currentFrame.getNextChild();
            // order == Pre_Order 先序遍历
            // order == In_Order 中序遍历
            // order == Post_Order 后序遍历
            if (child == next_child[order]) {
                ans.push_back(currentFrame.node->val);
            }
            if (child) {
                if (currentFrame.node->*child) {
                    Frame frame{currentFrame.node->*child};
                    st.push(currentFrame);
                    currentFrame = frame;
                }
                continue;
            }
            currentFrame.node = nullptr;
        }
        return ans;
    }
};

int main() {
    auto pre = Solution{}.traversal_simulate_stack(makeTree(), Pre_Order);
    cout << "Pre_Order:\t";
    for (auto v : pre) {
        cout << v << "\t";
    }
    cout << endl;

    cout << "In_Order:\t";
    auto in = Solution{}.traversal_simulate_stack(makeTree(), In_Order);
    for (auto v : in) {
        cout << v << "\t";
    }
    cout << endl;

    cout << "Post_Order:\t";
    auto post = Solution{}.traversal_simulate_stack(makeTree(), Post_Order);
    for (auto v : post) {
        cout << v << "\t";
    }
}

输出

在这里插入图片描述

后记

  多思考, 多思考, 希望有问题能积极沟通
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值