题目描述:请实现两个函数,分别用来序列化和反序列化二叉树
【分析】
二叉树的序列化:把二叉树用字符串表示的过程,空节点NULL用某个字符表示(如:#),同时每两个结点之间用逗号”,“隔开。
二叉树的反序列化:把字符串表示的二叉树恢复的过程。
字符减去'0'问题:单个数字字符去减 '0' 得到相应的整数。
比如:字符‘1’转换成数字1,‘1’对应二进制编码是49,在ASCII码里‘0’对应是48,所以实际上就是49-48=1。同理 ‘2’ 的ASCII是50。
ASCII码规律:a~z是97~122的二进制,A~Z是65~90的二进制
大写字母=小写字母-32 ;
空格的ASCII码是32。
/*
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==NULL){
return NULL;
}
string str;
SerializeCore(root,str);//Node2Str()递归,把结点转换为字符串存入str
//下来将str转为char*以便输出返回值
int length =str.length();//length和size返回长度都不包括'\0'
char* res = new char[length +1];//创建char *型返回值,加1是因为还要存'\0'
for(int i=0;i<length ;i++){//遍历str,放入char* 型容器中返回
res[i]=str[i];
}
res[length ]='\0';//字符串以'\0'结尾
return res;
}
/*前序遍历递归,把结点存到str字符串:空节点为#,两结点间用“,”隔开*/
void SerializeCore(TreeNode* root,string& str)
{
if(root==NULL)
{
str += '#';//加号+用来拼接字符串用,不是加减的意思
return;
}
string temp=to_string(root->val);
str += temp;//拼接字符串
str +=',';//两结点逗号隔开
SerializeCore(root->left,str);//递归左结点
SerializeCore(root->right,str);//递归右结点
}
/*反序列化:字符串转为二叉树*/
TreeNode* Deserialize(char *str) {
if(str==NULL){
return NULL;
}
TreeNode* res = DeserializeCore(&str);//字符串转为二叉树
return res;
}
// 递归时改变了str值使其指向后面的序列,因此要声明为char**
TreeNode* DeserializeCore(char **str){
// 到达叶节点时,调用两次,都返回null,所以构建完毕,返回父节点的构建
if(**str == '#')
{
(*str)++;
return NULL;
}
// 因为整数是用字符串表示,一个字符表示一位,先进行转换
int num = 0;
while(**str != ',' && **str != '\0')//每个节点循环一次,每取到一个节点终止,取下个结点时再循环
{
num = num * 10 + ((**str) - '0');//单个数字字符去减‘0’得到的就是数字本质见有道笔记
(*str)++;//后移一位
}
TreeNode* root = new TreeNode(num);//每一个节点都有一个值,把取到的num值存进去
if(**str == '\0')//字符结尾'\0'
{
return root;
}
else
{
(*str)++;
}
root->left = DeserializeCore(str);//递归
root->right = DeserializeCore(str);
return root;
}
};