Leetcode刷题-589&&590:遍历n叉树

1.题目描述

”n叉树定义

// 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;
    }
};
*/

1.1 前序遍历-589

给定一个 n 叉树的根节点 root ,返回 其节点值的前序遍历 。
n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

示例1:
在这里插入图片描述

输入:root = [1,null,3,2,4,null,5,6]
输出:[1,3,5,6,2,4]

示例2:

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[1,2,3,6,7,11,14,4,8,12,5,9,13,10]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-ary-tree-preorder-traversal

1.2 后序遍历590

给定一个 n 叉树的根节点 root ,返回 其节点值的 后序遍历 。
n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

在这里插入图片描述

示例1:

输入:root = [1,null,3,2,4,null,5,6]
输出:[5,6,3,2,4,1]

示例2:

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[2,6,14,11,7,3,12,8,4,13,9,10,5,1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-ary-tree-postorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-ary-tree-postorder-traversal

2.题目分析

模拟二叉树的递归与迭代方式实现,原理基本相同,细节部分见代码注释。

3.题目解答

3.1 前序遍历

3.1.1 前序递归

class Solution {
public:
    void preorderTraverse(Node* root,vector<int>& ivec){
        if(root == nullptr) return;
        ivec.push_back(root->val);
        for(Node *cur : root->children){
            preorderTraverse(cur,ivec);
        }
    }
    vector<int> preorder(Node* root) {
        vector<int> ivec;
        preorderTraverse(root,ivec);
        return ivec;
    }
};

3.1.2前序迭代

class Solution {
public:
    vector<int> preorder(Node* root) {
        vector<int> ivec;
        stack<Node*> st;
        if(root == nullptr)  return ivec;
        // 保存当前节点的子节点访问记录
        unordered_map<Node*,int> mni;
        Node* node = root;
        while(!st.empty() || node){
            while(node){
                ivec.emplace_back(node->val);
                st.push(node);
                // 只有当前节点有着子节点才能进行访问
                if(node->children.size()>0){
                    mni[node]=0;
                   node = node->children[0]; 
                } 
                else node = nullptr;
            }
            // 读取栈顶元素并操作
            node = st.top();
            // 获取上次访问此节点的子节点下标
            int index = mni.count(node)>0 ?mni[node]:-1;
            index+=1;
            // 如果子节点未访问完
            if(index < node->children.size()){
                mni[node]=index;
                node = node->children[index];
            }else{
            //若节点的子节点已经访问完,弹出此节点
                st.pop();
                mni.erase(node);
                node = nullptr;
            }
        }
        return ivec;
    }
};

3.2 前序遍历

3.2.1 后序递归

void postTraverse(Node* root,vector<int> &iv){
        if(root == nullptr) return;
        // 先遍历子节点,再遍历父节点
        for(int i=0;i<root->children.size();i++){
            postTraverse(root->children[i],iv);
        }
        iv.emplace_back(root->val);
    }
    vector<int> postorder(Node* root) {
        vector<int>ivec;
        postTraverse(root,ivec);
        return ivec;
    }

3.2.2 后序迭代

vector<int> postorder(Node* root) {
        vector<int>ivec;
        stack<Node*>st;
        if(root == nullptr) return ivec;
        Node *node = root;
        // 子节点访问记录标记
        unordered_map<Node*,int> mni;
        while(!st.empty() || node){
            //最左边下沉
            while(node){
                st.emplace(node);
                //若当前节点有子节点
                if(node->children.size() > 0){
                    mni[node] = 0;
                    node = node->children[0];
                }else{
                    node = nullptr;
                }
            }
            node = st.top();
            int index = mni.count(node)>0 ? mni[node]:-1;
            index+=1;
            if(index<node->children.size()){
                mni[node] = index;
                node = node->children[index];
            }else{
                // 元素出栈之前才能压入数组,
                // 出栈说明其子节点刚刚都访问完
                ivec.emplace_back(node->val);
                st.pop();
                mni.erase(node);
                node = nullptr;
            }
        }
        return ivec;
    }

总结:树的算法实现与其遍历密不可分,可以参考本文学习二叉树的遍历

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值