题目描述:
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
思路:
把二叉树转化为一个字符串,并且还能把这个字符串还原成原来的二叉树。
- 序列化:使用层次遍历,当遇到空节点时,向字符串内存入"#" , 当遇到非空节点时,向字符存入节点值。(节点之间用 “,” 分隔)。
- 反序列化:以 “,” 来将字符串进行拆分存入vector中,遍历整个容器,当前值如果是"#“就表示这个子节点是空的,如果不是”#"就表示不是空的,且相挨着的两个值为左右子树,以此构造出整颗二叉树。
实现代码:
string serialize(TreeNode* root) { //序列化
string res;
if(root == nullptr)
return "#";
queue<TreeNode*> que;
que.push(root);
while(!que.empty()){
TreeNode *p = que.front();
que.pop();
if(p == nullptr){
res.append("#,");
continue;
}
else{
res.append(to_string(p->val) + ",");
}
//不需要判断左右子树是否为空,为空仍需进入队列,以"#"存入字符串
que.push(p->left);
que.push(p->right);
}
return res;
}
vector<string> Stringsplit(string str, const char split) //用于分割字符串
{
vector<string> res;
istringstream iss(str); // 输入流
string token; // 接收缓冲区
while (getline(iss, token, split)) // 以split为分隔符
{
res.push_back(token);
}
return res;
}
TreeNode* deserialize(string data) { //反序列化
if(data == "#")
return nullptr;
vector<string> res = Stringsplit(data,','); //以','分割字符串。
TreeNode *root = new TreeNode(stoi(res[0]));
queue<TreeNode*> dl;
dl.push(root);
for(int i = 1; i < res.size(); i++)
{
TreeNode *p = dl.front();
dl.pop();
if(res[i] != "#"){ //左子树
int val = stoi(res[i]);
TreeNode *t = new TreeNode(val);
p->left = t;
dl.push(t);
}
if(res[++i] != "#" && i < res.size()){ //右子树
int val = stoi(res[i]);
TreeNode *t = new TreeNode(val);
p->right = t;
dl.push(t);
}
}
return root;
}