题目描述
请实现两个函数,分别用来序列化和反序列化二叉树
解题思路
如果二叉树序列化从根节点开始,那相应的反序列化在根节点的数值读出来时就可以开始了,无需等待很长时间。因此,可以根据前序遍历的顺序来序列化二叉树。在遍历二叉树遇到nullptr时,将其序列化为一个特殊字符(如'#')或数值。
1 string类
返回类型为char *,所以最后需要进行类型转换。
class Solution {
public:
void SerializeHelper(TreeNode *node, string& s) {
if (!node) {
s.push_back('#');
s.push_back(',');
return;
}
s += to_string(node->val);
s.push_back(',');
SerializeHelper(node->left, s);
SerializeHelper(node->right, s);
}
char* Serialize(TreeNode *root) {
if (!root) return nullptr;
string s = "";
SerializeHelper(root, s);
char *res = new char[s.length() + 1];
strcpy(res, s.c_str());
return res;
}
TreeNode* DeserializeHelper(string &s) {
if (s.empty()) return nullptr;
if (s[0] == '#') {
s = s.substr(2);
return nullptr;
}
TreeNode *res = new TreeNode(stoi(s));
s = s.substr(s.find_first_of(',') + 1);
res->left = DeserializeHelper(s);
res->right = DeserializeHelper(s);
return res;
}
TreeNode* Deserialize(char *str) {
if (!str) return nullptr;
string s(str);
return DeserializeHelper(s);
}
};
2 vector
不需要在每个结点之后再加分隔符。不过注意,访问时传入一级指针,只能拷贝地址,对该地址的数据进行操作,而无法对原来的地址进行操作;传入二级指针或者一级加引用传递指针时,对该指针的数据进行操作,就能改变原地址,从而便于访问下一数据,保证每次递归后指向字符串的指针会随着递归的进行而移动。
class Solution {
public:
vector<int> buf;
void dfs1(TreeNode *root) {
if(!root) buf.push_back(0xFFFFFFFF);
else {
buf.push_back(root->val);
dfs1(root->left);
dfs1(root->right);
}
}
char* Serialize(TreeNode* root) {
buf.clear();
dfs1(root);
int bufSize=buf.size();
int *res=new int[bufSize];
for(int i=0; i<bufSize; i++) res[i]=buf[i];
return (char*)res;
}
//
TreeNode* dfs2(int* &p) {
if(*p==0xFFFFFFFF) {
p++;
return nullptr;
}
TreeNode* res=new TreeNode(*p);
p++;
res->left=dfs2(p);
res->right=dfs2(p);
return res;
}
TreeNode* Deserialize(char* str) {
int *p=(int*)str;
return dfs2(p);
}
};
3 stringstream
class Solution {
public:
string sHelper(TreeNode *node) {
if (!node) return "#";
return to_string(node->val)+","+sHelper(node->left)+","+sHelper(node->right);
}
char* Serialize(TreeNode *root) {
string s = sHelper(root);
char *ret = new char[s.length()+1];
strcpy(ret, s.c_str());
return ret;
}
/
TreeNode *dHelper(stringstream &ss) {
string str;
getline(ss, str, ',');
if (str == "#") return NULL;
else {
TreeNode *node = new TreeNode(stoi(str));
node->left = dHelper(ss);
node->right = dHelper(ss);
return node;
}
}
TreeNode* Deserialize(char *str) {
stringstream ss(str);
return dHelper(ss);
}
};
其中,stoi函数为系统自带string转int函数,可自定义如下
int string_to_int(string str){
stringstream s;
int res;
s << str;
s >> res;
return res;
}
4 queue
class Solution {
public:
char* Serialize(TreeNode *root) {
queue<TreeNode*> Q;
string vec;
char *res = "";
if(!root) return res;
Q.push(root);
while(!Q.empty()){
int len = Q.size();
string tmp;
for(int i = 0; i < len; ++i){
TreeNode* p = Q.front(); Q.pop();
if(!p) {
vec += "# ";
continue;
}
vec += to_string(p->val) + " ";
Q.push(p->left);
Q.push(p->right);
}
}
res = strdup(vec.c_str());
return res;
}
TreeNode* Deserialize(char *str) {
if(!strlen(str)) return NULL;
string s = "";
while(*str != '\0'){
s += *str;
++str;
}
istringstream in(s);
queue<TreeNode*> Q;
string val;
in >> val;
if(val == "" || val == "#") return NULL;
TreeNode* p = new TreeNode(string_to_int(val));
Q.push(p);
while(!Q.empty()){
TreeNode* t = Q.front(); Q.pop();
if(!(in >> val)) break;
if(val != "#"){
TreeNode* pp = new TreeNode(stoi(val));
Q.push(pp);
t->left = pp;
}
if(!(in >> val)) break;
if(val != "#"){
TreeNode* pp = new TreeNode(stoi(val));
Q.push(pp);
t->right = pp;
}
}
return p;
}
};