剑指Offer JZ61 序列化二叉树 C++实现

题目描述

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

二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。

二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。

例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己的函数来解析回这个二叉树

解题思路


方法一:层次遍历

1、思路:层次遍历二叉树,在序列化过程中,如果当前结点不是空结点,则不管当前结点的左右结点是否为空,都加入队列。遇到空结点则对字符串拼接"#!",否则拼接结点值和'!'。

反序列化时,再模拟一次层次遍历,首先将根结点构造出来入队,然后在字符串中过滤根节点,查看字符串当前结点值:如果为'#',则左结点为空,过滤"#!",否则构造左结点,然后入队并在字符串中过滤左结点;再次查看字符串当前结点值:如果为'#',则右结点为空,过滤"#!",否则构造右结点,然后入队并在字符串中过滤右结点。重复上述过程直到队列为空或字符串为空。

2、代码:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    char* Serialize(TreeNode *root) {    
        if (!root) return nullptr;
        string tmp;
        queue que;
        que.push(root);
        TreeNode *cur = nullptr;
        while (!que.empty()) {
            cur = que.front();
            que.pop();
            if (cur != nullptr) {
                tmp = tmp + to_string(cur->val) + '!';
                que.push(cur->left);
                que.push(cur->right);
            } else {
                tmp = tmp + '#' + '!';
            }
        }
        char *result = new char[tmp.length() + 1]; //   '\0'
        strcpy(result, tmp.c_str());
//         copy(tmp.begin(), tmp.end(), result);
        return result;
    }
    TreeNode* Deserialize(char *str) {
        if (!str) return nullptr;
        string s(str);
        if (s[0] == '#') return nullptr;
        TreeNode *root = new TreeNode(atoi(s.c_str()));
        s = s.substr(s.find_first_of('!') + 1); //过滤根节点
        queue que;
        que.push(root);
        TreeNode *cur = nullptr;
        while (!que.empty() && !s.empty()) {
            cur = que.front();
            que.pop();
            if (s[0] == '#') {
                cur->left = nullptr;
                s = s.substr(2);    //过滤 "#!"
            } else {
                cur->left = new TreeNode(atoi(s.c_str()));
                que.push(cur->left);
                s = s.substr(s.find_first_of('!') + 1);
            }
            if (s[0] == '#') {
                cur->right = nullptr;
                s = s.substr(2);
            } else {
                cur->right = new TreeNode(atoi(s.c_str()));
                que.push(cur->right);
                s = s.substr(s.find_first_of('!') + 1);
            }
        }
        return root;
    }
};

3、复杂度:

时间复杂度:O(n);

空间复杂度:O(n)。


方法二:前序遍历

1、思路:前序遍历递归二叉树。序列化的过程套用前序遍历模板,反序列化的过程类似。

2、代码:

class Solution {
public:
    char* Serialize(TreeNode *root) {    
        if (!root) return "#!";
        string s;
        s = to_string(root->val) + '!';
        char *left = Serialize(root->left);
        char *right = Serialize(root->right);
        char *result = new char[s.size() + strlen(left) + strlen(right) + 1];
        s = s + string(left) + string(right);
        strcpy(result,s.c_str());
//         strcat(result,left);
//         strcat(result,right);
        return result;
    }
    TreeNode* deser(char *&str) {
        if (*str == '#') {
            str = str + 2;
            return nullptr;
        }
        int num = atoi(str);
        while (*str != '!') {
//             num = num * 10 + (*str - '0');
            str++;
        }
        str++;
        TreeNode *root = new TreeNode(num);
        root->left = deser(str);
        root->right = deser(str);
        return root;
        
    }
    TreeNode* Deserialize(char *str) {
        return deser(str);
    }
};

3、复杂度:

时间复杂度:O(n);

空间复杂度:O(n)。

你可能感兴趣的:(剑指Offer)