序列化二叉树
题目链接
请实现两个函数,分别用来序列化
和反序列化
二叉树。
你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
提示:
输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。
你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
示例:
输入:root = [1,2,3,null,null,4,5]
输出:[1,2,3,null,null,4,5]
解题思路
序列化
- 对二叉树序列化的大概有四种方法:先序遍历,中序遍历,后序遍历,层序遍历。
- 本题我选择了先序遍历,先序遍历代码如下:
string dfs(TreeNode* root){
if(root==NULL)return "#,";
string s=to_string(root->val)+',';
s+=dfs(root->left);
s+=dfs(root->right);
return s;
}
反序列化
- 反序列化就是将序列化的字符串还原成树结构。
- 序列化的字符串,举个例子
1,2,#,#,3,4,#,#,5,#,#,
,有这样的特点:先是根节点,再是左子树的节点,再是右子树的节点。 - 那么我们可以先构建根节点,难点在于那部分是左子树节点,那部分是右子树节点呢?
- 我们可以使用STL库函数的
list
,将字符串转换成list
。 - 转换的代码如下:
list<string>arr;
string s;
for(int i=0;i<data.length();i++){
if(data[i]==','){
arr.push_back(s);
s.clear();
}
else{
s.push_back(data[i]);
}
}
- 这样的话每构建一个节点就把该节点从
list
中删除,复杂度为 O ( 1 ) O(1) O(1) - 等根节点和左子树构建完毕,剩下的必然是右子树。
- 核心代码如下:
TreeNode* t=new TreeNode(to_val(arr.front()));
arr.erase(arr.begin());
t->left=build(arr);
t->right=build(arr);
解题代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
string to_string(int val){
string ans="";
while(val){
ans+=val%10+'0';
val/=10;
}
reverse(ans.begin(),ans.end());
return ans;
}
int to_val(string s){
int ans=0;
for(int i=0;i<s.length();i++){
ans=ans*10+(int)(s[i]-'0');
}
return ans;
}
string dfs(TreeNode* root){
if(root==NULL)return "#,";
string s=to_string(root->val)+',';
s+=dfs(root->left);
s+=dfs(root->right);
return s;
}
string bfs(TreeNode* root){
queue<TreeNode*>q;
q.push(root);
string s="";
while(!q.empty()){
TreeNode* t=q.front();
q.pop();
if(t==NULL){
s+="#,";
continue;
}
else s+=to_string(t->val)+',';
q.push(t->left);
q.push(t->right);
}
return s;
}
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string s=dfs(root);
return s;
}
TreeNode* build(list<string>&arr){
// list<string>::iterator it=arr.begin();
// for(;it!=arr.end();it++){
// cout<<*it<<" ";
// }cout<<endl;
if(arr.front()=="#"){
arr.erase(arr.begin());
return NULL;
}
TreeNode* t=new TreeNode(to_val(arr.front()));
arr.erase(arr.begin());
t->left=build(arr);
t->right=build(arr);
return t;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
list<string>arr;
string s;
for(int i=0;i<data.length();i++){
if(data[i]==','){
arr.push_back(s);
s.clear();
}
else{
s.push_back(data[i]);
}
}
TreeNode* tree=build(arr);
return tree;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));