持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
一、题目
描述:
请实现两个函数,分别用来序列化和反序列化二叉树,不对序列化之后的字符串进行约束,但要求能够根据序列化之后的字符串重新构造出—棵与原二叉树相同的树。
#include<iostream>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
inline TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
char* serialize(TreeNode *root) {
}
TreeNode* deserialize(char *str) {
}
int main(int, char*[])
{
TreeNode root(1);
TreeNode node1(2);
TreeNode node2(3);
TreeNode node3(6);
TreeNode node4(7);
root.left = &node1;
root.right = &node2;
node2.left = &node3;
node2.right = &node4;
char* data = serialize(&root);
TreeNode* node = deserialize(data);
cout << node->val << endl;
cout << node->left->val << endl;
cout << node->right->val << endl;
cout << node->right->left->val << endl;
cout << node->right->right->val << endl;
}
二、分析
老规矩,对于动态申请内存的操作能避免则避免,题中规定节点数小于等于100,再加上叶子节点最多36个,每个叶子结点两个空子节点,也就是100+36*2=172,总共需要申请172的空间,但是如果考虑没有规定节点数的情况,本着兼容的原则,还是老老实实遍历获取总节点数吧。
题中规定数值不超过150,也就意味着我们最多使用1个字节就可以表示一个数,所以序列化的时候可以使用字节表示法,这样就可以避免使用逗号或者其他符号来讲数字隔开,也省去了分离的步骤,因为我们可以确定一个字节就是一个数,而空节点就可以使用151~255之间的数字来表示。
接着就是确定遍历顺序了,这里对于遍历顺序没有特殊注意的,先序中序后序皆可,因为我们是表示了空节点的,哪种顺序都能构建成功,但是从简单程度上来看,先序遍历会好一些,因为先序遍历每一步都是连上的,而中序和后序是有先构建子树再连接的情况,不利于逻辑推理。
三、模拟
- 1 "1"
- 1 -> 2 "12"
- 2 -> 空左 "12#"
- 2 -> 空右 "12##"
- 1 -> 3 "12##3"
- 3 -> 6 "12##36"
- 6 -> 空左 "12##36#"
- 6 -> 空右 "12##36##"
- 3 -> 7 "12##36##7"
- 7 -> 空左 "12##36##7#"
- 7 -> 空右 "112##36##7##"
- 遍历结束
四、实现
inline char toChar(int& i){
return static_cast<char>(static_cast<unsigned char>(i));
}
inline int toInt(char& c){
return static_cast<int>(static_cast<unsigned char>(c));
}
void serializeDfs(TreeNode *root, char* data, int& cursor) {
static char none = static_cast<char>(static_cast<unsigned char>(151));
if(root){
data[cursor] = toChar(root->val);
++cursor;
serializeDfs(root->left, data, cursor);
serializeDfs(root->right, data, cursor);
}else{
data[cursor] = none;
++cursor;
}
}
void serializeCount(TreeNode *root, int& count) {
++count;
if(root){
serializeCount(root->left, count);
serializeCount(root->right, count);
}
}
char* serialize(TreeNode *root) {
int count = 0;
if(root){
serializeCount(root, count);
}
char* data = new char[count + 1];
data[count] = 0;
int cursor = 0;
serializeDfs(root, data, cursor);
return data;
}
TreeNode* deserializeDfs(char *str, int& cursor) {
static char none = static_cast<char>(static_cast<unsigned char>(151));
char& c = str[cursor];
++cursor;
if(c == none) return nullptr;
TreeNode* node = new TreeNode(toInt(c));
node->left = deserializeDfs(str, cursor);
node->right = deserializeDfs(str, cursor);
return node;
}
TreeNode* deserialize(char *str) {
if(!*str) return nullptr;
int cursor = 0;
return deserializeDfs(str, cursor);
}
五、结言
这道题主要还是对二叉树遍历算法在实际中的一种应用,熟练掌握基础算法很重要。
创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!