你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
输入:root = [1,2,3,null,null,4,5]
输出:[1,2,3,null,null,4,5]
思路一: 深度优先搜索
利用先序遍历,递归的遍历每一个节点:
- 如果当前节点不为空,就将当前节点对应元素加入到字符串中,然后加入逗号字符串(用来标记每个字符)
- 若当前节点为空,我们就将“None”字串加入到字符串,然后加入逗号字符串
下面这个例子:
从跟节点1
开始,序列化字符串是1,
。然后跳到根节点2
的左子树,序列化字符串变成1,2,
。。。
最后序列化字符串应该是1,2,3,None,None,4,None,None,5,None,None,
。
反序列化呢?
首先根据,
把原先的序列分割开来得到先序遍历的元素列表,然后从左向右遍历这个序列:
- 如果当前的元素为None,则当前为空树
- 否则先构建左子树,然后构建右子树
class Codec {
public:
void serializeDfs(TreeNode* root, string& s) {
if(root == nullptr) {
s += "None,";
}else {
s += to_string(root->val) + ",";
serializeDfs(root->left, s);
serializeDfs(root->right, s);
}
}
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string str;
serializeDfs(root, str);
return str;
}
TreeNode* deserializeDfs(list<string>& dataArray) {
if(dataArray.front() == "None") {
dataArray.erase(dataArray.begin());
return nullptr;
}
TreeNode* root = new TreeNode(stoi(dataArray.front()));
dataArray.erase(dataArray.begin());
root->left = deserializeDfs(dataArray);
root->right = deserializeDfs(dataArray);
return root;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
list<string> dataArray;
string str;
for(auto& ch : data) {
if(ch == ',') {
dataArray.push_back(str);
str.clear();
}
else {
str.push_back(ch);
}
}
return deserializeDfs(dataArray);
}
};
思路二: 广度优先搜索
利用层序遍历,按层遍历,对于队列中的当前节点:
- 如果当前节点不为空:访问节点,在队列中添加该队列的左、右子树
- 如果当前节点为空:字符串中添加
None,
反序列化借助队列:
首先根据,把原先的序列分割开来得到先序遍历的元素列表,然后从左向右遍历这个序列:
对于队列中的当前节点(父亲节点):
- 有左右孩子节点,就构建树
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string str;
if(root == nullptr) return str;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()) {
TreeNode* node = que.front();
que.pop();
if(node != nullptr) {
str += to_string(node->val) + ",";
que.push(node->left);
que.push(node->right);
}
else {
str += "None,";
}
}
return str;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
TreeNode* root;
if(data == "") return nullptr;
string s;
vector<string> vec;
//首先获取到去除,的字符串列表
for(auto& ch : data) {
if(ch == ',') {
vec.push_back(s);
s.clear();
}
else {
s += ch;
}
}
//构建二叉树
root = new TreeNode(stoi(vec[0]));
queue<TreeNode*> que;
que.push(root);
int index = 0;
while(!que.empty()) {
TreeNode* node = que.front();
que.pop();
//有左节点
if(vec[index * 2 + 1] != "None") {
node->left = new TreeNode(stoi(vec[index * 2 + 1]));
que.push(node->left);
}
//有右节点
if(vec[index * 2 + 2] != "None") {
node->right = new TreeNode(stoi(vec[index * 2 + 2]));
que.push(node->right);
}
index++;
}
return root;
}
};