[剑指Offer]:序列化二叉树

126 阅读2分钟

文章目录


题目描述

实现两个函数,分别用来序列化和反序列化二叉树。

示例:

你可以将以下二叉树:

    1
   / \
  2   3
     / \
    4   5

序列化为 "[1,2,3,null,null,4,5]"

题解思路

方法一:层序遍历

  • 序列化就是简单的层序遍历。
  • 在反序列化的时候,将字符串解析的过程中将新建的节点存入vector容器。
  • 根据节点间的顺序关系,构建连接树结构。

代码实现:

class Codec {
public:
    // Encodes a tree to a single string.
    // 队列层序遍历
    string serialize(TreeNode* root) {
        string res = "";
        if(!root) return res;

        queue<TreeNode*> qu;
        qu.push(root);
        TreeNode* cur = new TreeNode(0);
        while(!qu.empty()){
            // 记录队列里的元素长度
            int len = qu.size();
            while(len--){
                cur = qu.front();
                qu.pop();
                if(!cur) res += "null";
                else res += to_string(cur->val);
                res += ',';
                if(cur){
                    qu.push(cur->left);
                    qu.push(cur->right);
                }
            }
        }
        res.pop_back();
        return res;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        if(data.size() == 0) return nullptr;
        int len = data.size();
        int i = 0;
        vector<TreeNode*> v;
        while(i < len){
            //遇到逗号停下来。
            string str = "";
            while(i<len && data[i]!=','){
                str += data[i];
                i++;
            }
            if(str == "null"){
                TreeNode* tmp = nullptr;
                v.push_back(tmp);
            }
            else{
                int temp = stoi(str);
                TreeNode* cur = new TreeNode(temp);
                v.push_back(cur);
            }
            i++;
        }
        // 遍历v,构建二叉树
        for(int i = 0, j = 1; j < v.size(); ++i){
            if(!v[i]) continue;
            if(j < v.size()) v[i]->left = v[j++];
            if(j < v.size()) v[i]->right = v[j++];
        }
        return v[0];
    }
};

方法二:前序遍历

  • 递归遍历二叉树的节点,空节点使用#代替,节点之间使用逗号隔开,返回字符串
  • 反序列化的结果,就是根据先序遍历,再重建二叉树即可。

代码实现:

class Solution {
public:
    char* Serialize(TreeNode *root) {    
        if (!root) return "#";
     
        string res = to_string(root->val);
        res.push_back(',');
     
        char* left = Serialize(root->left);
        char* right = Serialize(root->right);
        char* ret = new char[strlen(left)+strlen(right)+res.size()];
        // 如果是string类型,直接用operator += ,这里char* 需要用函数
        strcpy(ret, res.c_str());
        strcat(ret, left);
        strcat(ret, right);
     
        return ret;
    }
    TreeNode* deseri(char *&s) {
        if (*s == '#') {
            ++s;
            return nullptr;
        }
     
        // 构造根节点值
        int num = 0;
        while (*s != ',') {
            num = num * 10 + (*s - '0');
            ++s;
        }
        ++s;
        // 递归构造树
        TreeNode *root = new TreeNode(num);
        root->left = deseri(s);
        root->right = deseri(s);
     
        return root;
    }
    TreeNode* Deserialize(char *str) {
        return deseri(str);
    }
};

如有不同见解,欢迎留言讨论~~~