剑指 Offer 37. 序列化二叉树

剑指 Offer 37. 序列化二叉树

在这里插入图片描述
解题思路

序列化二叉树:

  1. 首先判断树是否为空,空则直接返回"[]".

  2. 借助辅助队列,层序遍历二叉树,首先将"["加入str,并将根节点入队.

  3. 队列空则结束:
    1)获取队列首节点node,将首节点弹出.
    2)判断node是否为空,空则直接将"null"加入字符串str,非空则将当前节点node的值val加入字符串,并将node的左右子树节点加入队列.
    3)判断队列是否为空,非空将","加入str.

  4. 跳出循环将"]"加入str.

  5. 最后返回str.

反序列化二叉树:

  1. 判断序列表data是否为空,空则直接返回NULL.

  2. 获取data出去前后[]的字符串(使用stringstream获取到数据sstr中).

  3. 将得到的sstr用",“做分割获取其中的字符,getline一个一个获取”,"分割的字符.

  4. 将获取的第一个字符转化为整形(atoi(str.c_str()))作为val构造二叉树的根节点TreeNode* root = new TreeNode(atoi(str.c_str()));

  5. 将新创建的root节点加入队列.

  6. 队列空则结束:
    1)获取队列首节点cur,将首节点弹出.
    2)从数据流sstr中获取下一个字符;判断字符是否为空,非空则构造一个树节点lef,将此节点作为cur的左节点cur->left = lef;将lef节点加入到队列.
    4)从数据流sstr中获取下一个字符;判断字符是否为空,非空则构造一个树节rig,将此节点作为cur的右节点cur->right = rig;将rig节点加入到队列.

  7. 返回根节点root.

class Codec {
public:
    queue<TreeNode*> que;
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        //借助辅助队列层序遍历树种的节点
        if(root == NULL)
            return "[]";
        string str;
        str.append("[");
        que.push(root);
        while(!que.empty())
        {
            TreeNode *node = que.front();  //取出队列中的首节点
            que.pop();
            if(node != NULL)
            {
                str += to_string(node->val);
                que.push(node->left);
                que.push(node->right);
            }
            else
                str.append("null");
            if(!que.empty())
                str.append(",");
        }
        str.append("]");
        return str;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        if(data == "[]")
            return NULL;
        //从序列表中取出[]获取中间的字符串
        stringstream sstr(data.substr(1,data.size()-2)); //出去第一个[和最后一个]
        //从获取的字符串中用,分割出单个字符
        string str;
        getline(sstr,str,',');  //str中存放第一个,分割出的字符 1
        TreeNode *root = new TreeNode(atoi(str.c_str()));  //将str中的字符转换为整形构造根节点
        //将根节点入队
        que.push(root);
        while(!que.empty())
        {
            TreeNode *cur = que.front();
            que.pop();
            getline(sstr,str,',');
            if(str != "null")
            {
                TreeNode *lef = new TreeNode(atoi(str.c_str()));
                cur->left = lef;
                que.push(lef);
            }
            getline(sstr,str,',');
            if(str != "null")
            {
                TreeNode *rig = new TreeNode(atoi(str.c_str()));
                cur->right = rig;
                que.push(rig);
            }
        }
        return root;
    }
};

用到的其他相关知识:

C++中stringstream的用法
C++引入了ostringstream、istringstream、stringstream这三个类,要使用他们创建对象就必须包含sstream头文件。
istringstream类用于执行C++风格的串流的输入操作。
ostringstream类用于执行C风格的串流的输出操作。
stringstream类同时可以支持C风格的串流的输入输出操作。
sstream库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本。简单起见,我主要以stringstream为中心,因为每个转换都要涉及到输入和输出操作。

注意,使用string对象来代替字符数组。这样可以避免缓冲区溢出的危险。而且,传入参数和目标对象的类型被自动推导出来,即使使用了不正确的格式化符也没有危险。

c++中getline的用法

c++中有2种getline函数,一种在头文件 中,是istream类的成员函数;另一种是在头文件 中,是普通函数。

(一) 在头文件 的getline函数
两种重载形式:

  1. istream& getline (char* s, streamsize n );//读取最多n个字符保存在s对应的数组中,即使大小不够n,
  2. istream& getline (char* s, streamsize n, char delim ); //读取最多n个字符保存在s对应的数组中,遇到delim,或者读完一行,或字数达到限制则终止
    特别说明: 最多读取n个字符中结束字符算一位。

(二)在头文件中的getline函数

  1. istream& getline (istream& is, string& str, char delim);
    istream& getline (istream&& is, string& str, char delim);
  2. istream& getline (istream& is, string& str);
    istream& getline (istream&& is, string& str);
    说明:
    is:表示一个输入流,例如 cin。
    str:用来存储输入流中的信息
    delim:自定义结束字符,默认是 '\n ’
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值