刷题——对二进制树进行序列化和反序列化
原题:
其实我不怎么会这种类型的题目,所以这里的代码主要参考了九章上面的答案。
下面是我的代码:
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
vector<string> split(const string &str, string str2del){
vector<string> res_str;
int lastindex = 0;
int index = 0;
while((index = str.find(str2del, lastindex))!=string::npos){
res_str.push_back(str.substr(lastindex, index-lastindex));
lastindex = index + str2del.length();
}
if(lastindex!=str.length()){
res_str.push_back(str.substr(lastindex, str.length() - lastindex));
}
return res_str;
}
/**
* This method will be invoked first, you should design your own algorithm
* to serialize a binary tree which denote by a root node to a string which
* can be easily deserialized by your own "deserialize" method later.
*/
string serialize(TreeNode * root) {
if(root == NULL){
return "{}";
}
vector<TreeNode *> holder;
holder.push_back(root);
// cout << holder.size() << endl;
if(root == NULL){
return NULL;
}
// 用vector来存储节点内容,记住这里左边优先,后面复原的时候会用到
for(int i = 0; i < holder.size(); i++){
TreeNode * node = holder[i];
if (node == NULL){
continue;
}
holder.push_back(node->left);
holder.push_back(node->right);
}
// 因为节点末端检测的时候会检测到大量的NULL并被添加进holder中,所以需要移除掉
while(holder[holder.size() - 1]==NULL){
holder.pop_back();
}
string res_str = "{";
res_str += to_string(holder[0]->val);
for(int i = 1; i < holder.size(); i++){
if(holder[i] == NULL){
res_str+=",#";
}
else{
res_str+=",";
res_str+=to_string(holder[i]->val);
}
}
res_str+="}";
return res_str;
}
/**
* This method will be invoked second, the argument data is what exactly
* you serialized at method "serialize", that means the data is not given by
* system, it's given by your own serialize method. So the format of data is
* designed by yourself, and deserialize it here as you serialize it in
* "serialize" method.
*/
TreeNode * deserialize(string &data) {
if(data=="{}") return NULL;
vector<string> val = split(data.substr(1, data.size() - 2), ",");
queue<TreeNode *> Q;
TreeNode *root = new TreeNode(atoi(val[0].c_str()));
Q.push(root);
bool isLeftChild=true;
for(int i=1; i<val.size(); i++){
if(val[i]!="#"){
TreeNode *node = new TreeNode(atoi(val[i].c_str()));
if(isLeftChild) Q.front()->left = node;
else Q.front()->right = node;
Q.push(node);
}
if(!isLeftChild){
Q.pop();
}
// 当执行到右节点时则将当前处理的节点弹出,进入下一个节点(顶->左->右)
isLeftChild = !isLeftChild;
}
return root;
}
};
注释里面思路已经说得挺清楚的了,这里只是补充几句。总体上来看其实序列化要简单一点,直接遍历一遍树的内容并按照一定规律转化成字符串就可以了。其实这里用到vectoer是为了方便操作,大概的操作流程是:
序列化:
右边就是vector的情况(11之类的只是编号),左边的就是树的结构和内容。序列化的主要思路就是先将遍历一遍binary tree的内容,然后按照一定规律(记住,这里的规律是先左后右,后面反序列化的时候会用到这个规律)保存在vector中。
反序列化的流程差不多,只是加了个对上一层节点的弹出。
这里补充下相关的用法:C++ queue(STL queue)用法详解
虽然是queue的,但是实际上vector的也差不多,最重要的部分其实是这张图:
大概就是这样。
本博客文章默认使用CC BY-SA 3.0协议。