设计一个算法,并编写代码来序列化和反序列化二叉树。将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”。
如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列化为一个字符串,并且可以将字符串反序列化为原来的树结构。
样例
给出一个测试数据样例, 二叉树{3,9,20,#,#,15,7},表示如下的树结构:
3
/ \
9 20
/ \
15 7
这道题有递归和非递归两种解法,先看递归解法。首先需要接入输入和输出字符串流istringstream和ostringstream。对于序列化,从根节点开始,如果存在,则将值存入输出流,然后对其左右子节点进行递归。对于反序列化,先读入一个字符,生成根节点,然后再对根节点的左右子节点进行递归,代码如下:
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* This method will be invoked first, you should design your own algorithm
* to serialize a binary tree which denote by a root node to a string which
* can be easily deserialized by your own "deserialize" method later.
*/
string serialize(TreeNode *root) {
// write your code here
ostringstream out;
serialize(root, out);
return out.str();
}
void serialize(TreeNode *root, ostringstream &out) {
if (root) {
out << root->val << ' ';
serialize(root->left, out);
serialize(root->right, out);
} else {
out << "# ";
}
}
/**
* This method will be invoked second, the argument data is what exactly
* you serialized at method "serialize", that means the data is not given by
* system, it's given by your own serialize method. So the format of data is
* designed by yourself, and deserialize it here as you serialize it in
* "serialize" method.
*/
TreeNode *deserialize(string data) {
// write your code here
istringstream in(data);
return deserialize(in);
}
TreeNode* deserialize(istringstream &in) {
string val;
in >> val;
if (val == "#") return nullptr;
TreeNode *root = new TreeNode(stoi(val));
root->left = deserialize(in);
root->right = deserialize(in);
return root;
}
};
另一种是非递归解法,略复杂一些,需要借助queue来做,本质是BFS算法:
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* This method will be invoked first, you should design your own algorithm
* to serialize a binary tree which denote by a root node to a string which
* can be easily deserialized by your own "deserialize" method later.
*/
string serialize(TreeNode *root) {
// write your code here
ostringstream out;
queue<TreeNode*> q;
if (root) q.push(root);
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
if (t) {
out << t->val << ' ';
q.push(t->left);
q.push(t->right);
} else {
out << "# ";
}
}
return out.str();
}
/**
* This method will be invoked second, the argument data is what exactly
* you serialized at method "serialize", that means the data is not given by
* system, it's given by your own serialize method. So the format of data is
* designed by yourself, and deserialize it here as you serialize it in
* "serialize" method.
*/
TreeNode *deserialize(string data) {
// write your code here
if (data.empty()) return nullptr;
istringstream in(data);
queue<TreeNode*> q;
string val;
in >> val;
TreeNode *res = new TreeNode(stoi(val)), *cur = res;
q.push(cur);
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
if (!(in >> val)) break;
if (val != "#") {
cur = new TreeNode(stoi(val));
q.push(cur);
t->left = cur;
}
if (!(in >> val)) break;
if (val != "#") {
cur = new TreeNode(stoi(val));
q.push(cur);
t->right = cur;
}
}
return res;
}
};