leetcode 297. 二叉树的序列化与反序列化
// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string s;
if(!root) {
return s;
}
queue<TreeNode*> q;
TreeNode* tmp;
TreeNode* tmp1;
q.push(root);
while(!q.empty()){
tmp = q.front();
q.pop();
if(tmp->val != -2147483648) {
s.append(to_string(tmp->val));
s.append(",");
} else {
delete(tmp);
s.append("#,");
continue;
}
if(tmp->left) {
q.push(tmp->left);
} else {
tmp1 = new TreeNode(-2147483648);
q.push(tmp1);
}
if(tmp->right) {
q.push(tmp->right);
} else {
tmp1 = new TreeNode(-2147483648);
q.push(tmp1);
}
}
return s;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
vector<TreeNode*> v; // 用v模拟队列
TreeNode* root = NULL;
if(data.length() <= 1)
return NULL;
int start = 0;
int end = 0;
int curVectorNodeIndex = 0;
TreeNode* curDataNode = NULL;
int childNum = 0; // 0 是左孩子,1是右孩子,2 是下一个节点
int tmp;
int i;
// 确保 v 中有一个元素
end = (int)data.find(',', start);
start = end + 1;
if(data[end-1] == '#')
return NULL;
root = new TreeNode(atoi((data.substr(0, end)).c_str()));
curVectorNodeIndex = 0;
v.push_back(root);
// 遍历下一层的每个结点,用来确保将左右孩子赋值给当前层
// 下一层的元素个数=当前层的元素实体个数的2倍
while(start < data.length()) {
// size_type m
end = (int)data.find(',', start);
if(data[end-1] != '#') {
// data中遍历到的结点是实体结点
curDataNode = new TreeNode(atoi((data.substr(start, end-start)).c_str()));
v.push_back(curDataNode);
// 做亲子鉴定
if(childNum == 0) {
v[curVectorNodeIndex]->left = curDataNode;
childNum++;
} else if(childNum == 1) {
v[curVectorNodeIndex]->right = curDataNode;
childNum = 0;
curVectorNodeIndex++;
}
} else {
// data中遍历到的结点是空结点
if(childNum == 0) {
v[curVectorNodeIndex]->left = NULL;
childNum++;
} else if(childNum == 1) {
v[curVectorNodeIndex]->right = NULL;
childNum = 0;
curVectorNodeIndex++;
}
}
start = end + 1;
}
return v[0];
}
};
1 2 4 4 4
1 2 3 # # 4 5 6 7 # # # # 8 #
按层次序列化为:
1,2,3,#,#,4,5,#,#,#,#,
再反序列化:
用如下方式递进data:
while(start < data.length()) {
// size_type m
end = (int)data.find(',', start);
... ...
start = end + 1;
}
然后while中遍历的是当前层的节点
vector<TreeNode*> v 和 curVectorNodeIndex 指向的是当前遍历到节点对应的父结点
因为还要修改父结点的左右孩子指针,因此需要用vector来存储前面层的结点
curVectorNodeIndex 前进的条件是 父节点的右孩子赋值完毕
父节点的修改和子结点的遍历同步进行
附一段打印函数
void printTree(TreeNode* root){
if(!root)
return;
queue<TreeNode*> q;
TreeNode* tmp, *tmp1;
q.push(root);
while(!q.empty()){
tmp = q.front();
q.pop();
if (tmp->val != -2147483648)
cout << tmp->val << " ";
else {
cout <<"# ";
delete tmp;
continue;
}
if(tmp->left) {
q.push(tmp->left);
} else {
tmp1 = new TreeNode(-2147483648);
q.push(tmp1);
}
if(tmp->right) {
q.push(tmp->right);
} else {
tmp1 = new TreeNode(-2147483648);
q.push(tmp1);
}
}