题目:
请实现两个函数,分别用来序列化和反序列化二叉树
链接:
剑指Offer(第2版):P194
思路标签:
- 算法:递归
- 数据结构:二叉树
解答:
- 以前的先序和后序遍历序列重构二叉树存在缺点:
- 一是要求二叉树中没有数值相同的结点;
- 二是要求真个序列都读出后才能开始重构,如果序列是流式输入,那么就需要等待序列输出完毕才能完成二叉树的重构。
- 利用先序遍历,同时保存二叉树叶子结点的两个左右空结点为“$”,构成先序序列,那么利用这样的序列,就可以规避上面存在的两种缺点。
1. 用char数组保存二叉树序列化结果
- 利用char数组保存二叉树序列化结果的方法思想简单,但流程中需要注意处理一些细节,需要先用str保存,然后再转换为char数组。
- 同时,还需要注意明个节点之间需要有明确的符号来界定。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
char* Serialize(TreeNode *root) {
if(root == nullptr)
return nullptr;
std::string str;
Serialize(root, str);
char *ret = new char[str.length() + 1];
int i = 0;
for(; i < str.length(); ++i){
ret[i] = str[i];
}
ret[i] = '\0';
return ret;
}
void Serialize(TreeNode *root, string &str){
if(root == nullptr){
str += '$';
return;
}
string value = to_string(root->val);
str += value;
str += ',';
Serialize(root->left, str);
Serialize(root->right, str);
}
TreeNode* Deserialize(char *str) {
if(str == nullptr)
return nullptr;
TreeNode* ret = Deserialize(&str);
return ret;
}
TreeNode* Deserialize(char **str){
if(**str == '$'){
++(*str);
return nullptr;
}
int num = 0;
while(**str != '\0' && **str != ','){
num = num*10 + ((**str) - '0');
++(*str);
}
TreeNode* root = new TreeNode(num);
if(**str == '\0')
return root;
else
(*str)++;
root->left = Deserialize(str);
root->right = Deserialize(str);
return root;
}
};
2. 用输入输出流来保存二叉树序列
- 程序体量较小,但需要后序流的操作。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
void Serialize(TreeNode* pRoot, ostream& stream){
if(pRoot == nullptr){
stream << "$,";
return;
}
stream << pRoot->val << ',';
Serialize(pRoot->left, stream);
Serialize(pRoot->right, stream);
}
void Deserialize(TreeNode* pRoot, istream& stream){
int number;
if(ReadStream(stream, &number)){
*pRoot = new TreeNodeNode(number);
Deserialize((*pRoot->left), stream);
Deserialize((*pRoot->right), stream);
}
}
bool ReadStream(istream& stream, int* number){
if(stream.eof())
return false;
char buffer[32];
buffer[0] = '\0';
char ch;
stream >> ch;
int i = 0;
while(!stream.eof() && ch != ',')
{
buffer[i++] = ch;
stream >> ch;
}
bool isNumeric = false;
if(i > 0 && buffer[0] != '$')
{
*number = atoi(buffer);
isNumeric = true;
}
return isNumeric;
}
};