思路: 序列化二叉树即找一种顺序存储二叉树的结点,并以相同的方式能够读取序列重新构建。 换种说法,就是遍历二叉树,记录每个结点,再以同样的方式遍历就可以还原二叉树。 遍历的方法有四种:先序遍历、中序遍历、后序遍历、层次遍历,理论上只要以相同的方式序列化或者反序列化,都可以解题。 图片说明 方法一:先序遍历 具体做法: 创建两个功能函数用于递归。SerializeFunction函数负责先序递归,将结点转换为字符,因string类型更适合字符串相加,我采用先用string,再转换为char的策略。DeserializeFunction函数负责先序递归构建树,利用char的指针依次移动,识别结点的数值,加入树中。

class Solution {
public:
    //处理序列化的功能函数(递归)
    void SerializeFunction(TreeNode* root, string& str){
        if(root == NULL){// 如果指针为空,表示左子节点或右子节点为空,用#表示
            str += '#';
            return;
        }
        string temp = to_string(root->val); //根
        str += temp + '!';// 加!,区分结点 
        SerializeFunction(root->left, str); //左
        SerializeFunction(root->right, str);//右
    }
    char* Serialize(TreeNode *root) {    
        if(root == NULL) //处理空树
            return "#";
        string res;
        SerializeFunction(root, res);
        // 把str转换成char
        char* charRes = new char[res.length() + 1];
        strcpy(charRes, res.c_str());
        charRes[res.length()] = '\0';
        return charRes;
    }
    //处理反序列化的功能函数(递归)
    TreeNode* DeserializeFunction(char** str){
        // 到达叶节点时,构建完毕,返回继续构建父节点
        if(**str == '#'){ //双**表示取值
            (*str)++;
            return NULL;
        }
        // 数字转换
        int val = 0;
        while(**str != '!' && **str != '\0'){
            val = val * 10 + ((**str) - '0');
            (*str)++;
        }
        TreeNode* root = new TreeNode(val);
        if(**str == '\0') //序列到底了,构建完成
            return root;
        else
            (*str)++;
        root->left = DeserializeFunction(str);  //反序列化与序列化一致,都是先序
        root->right = DeserializeFunction(str);
        return root;
    }
    TreeNode* Deserialize(char *str) {
        if(str == "#"){ //空序列对应空树
            return NULL;
        }
        TreeNode* res = DeserializeFunction(&str);
        return res;
    }
};

复杂度分析:

  • 时间复杂度:O(n),先序遍历,每个结点遍历一遍
  • 空间复杂度:O(n),递归栈最大深度