N叉树的前后遍历非递归

1.树的前序遍历

规律:访问根节点->访问根节点的子树

使用leetcode的题目来说明。
在这里插入图片描述

使用递归来做很简单,将问题抽象为:
输出根节点 − > 处理子树 输出根节点->处理子树 输出根节点>处理子树

递归的步骤:
递归的目的 − > 逻辑处理 − > 递归边界 递归的目的->逻辑处理->递归边界 递归的目的>逻辑处理>递归边界

1.递归的目的:输出树的前序遍历
2递归的逻辑处理:输出根节点->处理子树
3.递归的边界:当树为空的时候返回

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution 
{
public:
    vector<int> preorder(Node* root) 
    {
        vector<int>ans;
        function<void(Node *)>dfs=[&](Node *root)->void
        {
            if(root==NULL)return;  //边界处理

            ans.push_back(root->val);  //输出根节点

            for(int i=0;i<root->children.size();i++)   //处理子树
                dfs(root->children[i]);

            return; //可写可不写
        };

        dfs(root);
        return ans;
    }
};

难点来了,如果要使用非递归的方法怎么办。实际上,在计算机内存中,递归的过程,就是一个模拟栈的过程,遵从先进后出,后进先出的原理。每层递归的参数都会保存下来,等到递归回溯的时候才会将参数给回收。

比如:

定义一个递归方程:

void dfs(int i,int j)
{
	int a=i;
	int b=j;
	if(a==5&&b==5)return;
	dfs(a+1,b+1);
}
dfs(1,1);  //调用递归函数

递归进入的时候:

在这里插入图片描述

所以如果使用非递归的方法,就要创建一个栈来模拟递归的过程,也就是把递归过程中的栈”显化“出来。

前序遍历的栈调用是:放进第一个子树->放进第一个子树的子树->放进第一个子树的子树的子树。。
然后,出去栈顶的子树,放进出去子树的第二个子树,放进出去子树的第二个子树的第一个子树。。。

以下是模拟递归过程,
关键在于:
进栈的数据,不能只考虑当下,要同时考虑退栈的时候是否符合递归的逻辑,一进一出,有的“隐形”的数据要找到。只有这样才能具体化递归过程

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution 
{
public:
    vector<int> preorder(Node* root) 
    {
        vector<int>ans;
        stack<pair<Node*,int>>st;  //{当前节点,当前节点子树的下标(还没有访问)}
        if(root==NULL)return ans;
        st.push({root,0});
        ans.push_back(root->val);
        while(st.size())
        {
            pair<Node*,int>t=st.top();
            Node* r=t.first;
            if(t.second>=r->children.size())  //当前根节点的所有子树都被遍历过了,退栈。
            {
                st.pop();
                continue;
            }
            r=r->children[t.second];
            while(r!=NULL)  // 入栈孩子节点
            {
                st.top().second++;
                st.push({r,0});
                ans.push_back(r->val);
                if(r->children.size()==0)
                    break;
                else 
                    r=r->children[0];
            }
        }
        return ans;
    }
};

看了一下题解,发现一个更舒服的做法,很厉害

class Solution 
{
public:
    vector<int> preorder(Node* root) 
    {
        vector<int> res;
        stack<Node*> st;
        if(root == nullptr) return res;
        st.push(root);
        while(!st.empty())
        {
            Node* node = st.top();
            st.pop();
            res.push_back(node->val);
            for(int i = node->children.size() - 1; i >= 0; --i)
            {
                st.push(node->children[i]);
            }
        }
        return res;
    }
};

2.后序遍历

在这里插入图片描述

处理根节点的子树 − > 输出根节点 处理根节点的子树->输出根节点 处理根节点的子树>输出根节点


/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution 
{
public:
    vector<int> postorder(Node* root) 
    {
        vector<int>ans;
        function<void(Node*)>dfs=[&](Node*root)->void
        {
            if(root==NULL)return;
            for(int i=0;i<root->children.size();i++)  //处理完子树
            {
                dfs(root->children[i]);
            }
            ans.push_back(root->val);  //输出根节点
        };
        dfs(root);
        return ans;
    }
};

模拟递归过程,找葫芦画瓢呗,前序遍历用了两种写法,这个也用两种非递归写法

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution 
{
public:
    vector<int> postorder(Node* root) 
    {
        vector<int>ans;
        stack<pair<Node*,int>>st;
        if(root==NULL)
            return ans;
        st.push({root,0});
        while(st.size())
        {
            pair<Node*,int>t=st.top();
            Node *r=t.first;
            if(t.second==r->children.size())  //当前的节点的子树都处理完了,退栈,输出当前接节点
            {
                st.pop();
                ans.push_back(r->val);
                continue;
            }
            r=r->children[t.second];
            while(r!=NULL)
            {
                st.top().second++;
                st.push({r,0});
                if(r->children.size()==0)
                    break;
                else 
                    r=r->children[0];
            }
        }
        return ans;
    }
};
    vector<int> postorder(Node* root) 
    {
        vector<int> ans;
        if(root == nullptr) 
        {
            return ans;
        }
        stack<Node*> stk;
        stk.push(root);
        Node *pre = nullptr;
        while(!stk.empty()) 
        {
            Node *top = stk.top();
            if(top->children.size() != 0 && pre != top->children.back()) 
            {
                for(auto it = top->children.rbegin(); it != top->children.rend(); ++it) 
                {
                    stk.push(*it);
                }
                continue;
            }
            // 叶节点,或者上一个访问的节点是这个节点的最后一个字节点,那么访问当前节点
            ans.emplace_back(top->val);
            pre = top;
            stk.pop();
        }
        return ans;
    }

3.中序遍历(二叉树,N叉树没得中序遍历)

在这里插入图片描述
处理左子树 − > 处理根节点 − > 处理右子树 处理左子树->处理根节点->处理右子树 处理左子树>处理根节点>处理右子树

递归:

/**
 * 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> inorderTraversal(TreeNode* root) 
    {
        vector<int>ans;
        if(root==NULL)return ans;
        function<void(TreeNode*)>dfs=[&](TreeNode* root)->void
        {
            if(root==NULL)return;
            dfs(root->left);
            ans.push_back(root->val);
            dfs(root->right);
        };
        dfs(root);
        return ans;
    }
};

非递归:

/**
 * 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> inorderTraversal(TreeNode* root) 
    {
        vector<int>ans;
        if(root==NULL)return ans;
        //处理左子树--输出根节点--处理右子树
        stack<pair<TreeNode*,int>>st;
        st.push({root,0});
        while(st.size())
        {
            pair<TreeNode*,int>t=st.top();
            TreeNode *r=t.first;

            if(t.second==1||r->left==NULL)  //左子树为空或者遍历完左子树了
            {
                ans.push_back(r->val);  //加入当前节点
                st.pop();
                r=r->right;  
            }
            else  r=r->left; //否则栈顶节点的左子树还没有访问过

            while(r!=NULL)  //如果子树不为空
            {
                if(st.size())  //特殊处理,有可能上面的pop操作导致栈里面没有节点了
                    st.top().second=1; //当前节点的左子树不为空,标记栈顶节点,下次再遍历栈顶节点就知道它的左子树遍历过了,直接遍历右子树
                st.push({r,0});
                r=r->left;
            }
        }
        return ans;
    }
};
### STM32CubeMX Version 6.10.0 Download and Information For obtaining the specific version of STM32CubeMX, such as version 6.10.0, one should visit STMicroelectronics' official website or repository dedicated to software releases. The latest versions are typically available on the homepage; however, for older but specified versions like 6.10.0, navigating through the archive section might be necessary[^1]. Once at the site: - Search for "STM32CubeMX". - Navigate towards the downloads area. - Look specifically for archived versions where users can find a list of all released versions including detailed release notes that outline changes, improvements, bug fixes, etc., which is crucial when targeting an exact version number. Regarding installation after downloading, it follows standard procedures applicable across various operating systems. For integrating with development environments like MDK, ensuring corresponding device packs are installed remains critical. Device selection within tools like CubeMX requires having these packs because they provide support files needed by both IDEs (Integrated Development Environments) and configuration utilities alike[^2]. ```bash # Example command line instruction to check current version post-installation may vary based on OS stm32cubemx --version ``` --related questions-- 1. How does installing different device pack versions affect project compatibility? 2. What new features were introduced in STM32CubeMX from V4.17.0 to V6.10.0? 3. Can projects created in earlier versions of STM32CubeMX open seamlessly in later versions without issues? 4. Where can developers access comprehensive documentation about each STM32CubeMX update? 5. Is there any significant difference between using STM32CubeMX online versus offline modes?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值