思路: 序列化二叉树即找一种顺序存储二叉树的结点,并以相同的方式能够读取序列重新构建。 换种说法,就是遍历二叉树,记录每个结点,再以同样的方式遍历就可以还原二叉树。 遍历的方法有四种:先序遍历、中序遍历、后序遍历、层次遍历,理论上只要以相同的方式序列化或者反序列化,都可以解题。 方法一:先序遍历 具体做法: 创建两个功能函数用于递归。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),递归栈最大深度