二叉树的序列化和反序列化
作用
由于树结构是二维的,在输入输出时,这样的结构不是很好表示,所以需要使用一种方式将树结构转换成一种易于输入输出的形式表示,同时不失树的结构特性。
把树转换成线性结构单元(如数组)称做序列化,把线性结构单元(如数组)还原成树结构称作反序列化。
代码
#include <bits/stdc++.h>
using namespace std;
// 二叉树结构
typedef struct TreeNode{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x),left(NULL),right(NULL) {}
} TreeNode;
//注意:to_string()函数是非标准库中的函数,但是被包含在<bits/stdc++.h>中,由于本人本地IDE的问题无法使用to_string()函数,故自己实现了给函数方法。并未考虑到效率问题。
//作用:将数字由int类型转变成string类型。
string to_string(int num){
string result;
stringstream ss;
ss << num;
ss >> result;
return result;
}
// 二叉树的序列化和反序列化类
class SerializeAndDeserialize{
private:
// 分割函数
// 作用:将字符串按照某种规则分割成字符串片段
vector<string> split(string& data,char stop){
vector<string> result;
string temp;
for (int i = 0;i < (int)data.size();++i){
if (data[i] == stop){
result.push_back(temp);
temp = "";
}
else temp += data[i];
}
return result;
}
// 将数字由string类型转换成int类型
int Str2Int(string& s){
long num = 0;
int flag = 1;
for (int i = 0;i < (int)s.size();++i){
if (i == 0 && s[i] == '-') {
flag = -1;
continue;
}
num = num * 10 + (s[i] - '0');
}
return (int)(num * flag);
}
public:
// 序列化方法
// 使用广度优先搜索序列化二叉树
string serialize(TreeNode *root){
string data;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()){
auto cur = q.front();
q.pop();
if (cur != NULL){
data += (to_string(cur->val) + ',');
q.push(cur->left);
q.push(cur->right);
}
else data += "NULL,";
}
return data;
}
// 反序列化方法
TreeNode* deserialize(string data){
auto v = split(data,',');
queue<TreeNode*> q;
if (v[0] == "NULL") return NULL;
TreeNode *root = new TreeNode(Str2Int(v[0]));
q.push(root);
int i = 1,n = v.size();
while (i < n){
if (v[i] != "NULL"){
TreeNode *temp = new TreeNode(Str2Int(v[i]));
q.front()->left = temp;
q.push(temp);
}
++i;
if (v[i] != "NULL"){
TreeNode *temp = new TreeNode(Str2Int(v[i]));
q.front()->right = temp;
q.push(temp);
}
++i;
q.pop();
}
return root;
}
};
// 辅助函数
void helper(TreeNode* root,vector<int>& result){
if (root == NULL) return ;
helper(root->left,result);
helper(root->right,result);
result.push_back(root->val);
return ;
}
// 后序遍历
vector<int> postorder(TreeNode* root){
vector<int> result;
helper(root,result);
return result;
}
// 主函数
// 测试序列化和反序列化是否成功实现
int main(void){
string data;
getline(cin,data);
// data = "1,2,3,NULL,NULL,4,5,"
SerializeAndDeserialize f;
TreeNode *root = f.deserialize(data);
auto result = postorder(root);
for (int num : result) cout << num << " ";
cout << endl;
string res = f.serialize(root);
cout << res << endl;
return 0;
}
写在最后
二叉树的序列化和反序列化方法是有多种实现方式的,有兴趣的可以自己探索效率更高,思路更简洁的方法。
尽管二叉树的序列化和反序列化方法不属于常用的算法之一,但是该算法实现的功能却是很实用的,值得掌握。