297. 二叉树的序列化与反序列化 - 力扣(LeetCode)
前序遍历,dfs
class Codec {
public:
//编码:1_2_#_#_3_4_#_#_5_#_#_
string serialize(TreeNode* root) {//先序遍历
if(!root) return "#_";
return to_string(root->val) + "_" + serialize(root->left) + serialize(root->right);//根左右
}
// Decodes
TreeNode* deserialize(string data) {
cout << data << endl;
queue<string> q;
stringstream ss(data);
string s;
while(getline(ss, s, '_')) q.push(s);//碰到'_'中止读取
return help(q);
}
TreeNode* help(queue<string> &q){
auto cur = q.front(); q.pop();
if(cur == "#") return NULL;
auto root = new TreeNode(stoi(cur));
root->left = help(q);
root->right = help(q);
return root;
}
};
参考:c++ 队列 官方序列化方式 【面试题37. 序列化二叉树】 - 序列化二叉树 - 力扣(LeetCode)
使用层次遍历:
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {//层次遍历
string res;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
auto cur = q.front();
q.pop();
if(cur){
res += to_string(cur->val) + " ";
q.push(cur->left);//无论是否为null都要进入队列
q.push(cur->right);
}
else res += "# ";//cur为null是加上标记
}
//cout << res << endl;
return res;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
istringstream input(data);
vector<TreeNode*> vec;
string tmp;
while(input >> tmp){
if(tmp == "#") vec.push_back(NULL);
else vec.push_back(new TreeNode(stoi(tmp)));
}
int j = 1;
//i一次循环后移一位,j后移两位
//j始终指向i对应节点的左子树
for(int i = 0; j < vec.size(); ++i){//j比i快,j到头就可以跳出循环了
if(!vec[i]) continue;
if(j < vec.size()) vec[i]->left = vec[j++];
if(j < vec.size()) vec[i]->right = vec[j++];
}
return vec[0];
}
};
之所以要使用istringstream来处理,而不是挨个字符处理,是因为数字可能是负数或者多位数,这样的话拼接的字符串就不止一位。当然也不是非要使用字符流,只要能处理好多位数用什么都可以(挨个取子串也行)。