序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。
设计一个算法来序列化和反序列化二叉搜索树。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。
编码的字符串应尽可能紧凑。
注意:不要使用类成员/全局/静态变量来存储状态。 你的序列化和反序列化算法应该是无状态的。
思路分析:请先翻阅 LeetCode 二叉树的序列化与反序列化
由于二叉搜索树是二叉树的一种特殊情况,所以直接套用上题的代码即可。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string result = "[";
queue<TreeNode*> myQue;//层次遍历辅助队列
myQue.push(root);
while (!myQue.empty()) {
root = myQue.front();
myQue.pop();
if (root == NULL) {//特殊情况
result += "null,";
continue;
}
else {//这里不管左右子树是否为空,都需要入队列
result += to_string(root->val) + ",";
myQue.push(root->left);
myQue.push(root->right);
}
}
//示例给出的序列化字符串为"[1,2,3,null,null,4,5]"
//而按照上面的层次遍历得到的结果是"[1,2,3,null,null,4,5,null,null,null,null]"
//因为当访问到最底层的节点时,左右子树不管都为空,任然会进入队列。
//所以下面需要进行处理
if (result == "[null,") {//如果这棵树为空,只需要去逗号
result.resize(result.size() - 1);
}
else {//否则需要去掉多余的逗号、null
int endIndex = result.size() - 1;
//需要去掉末尾的逗号和多余的null
while (result[endIndex] < '0' || result[endIndex] > '9') {
endIndex -= 1;
}
result.resize(endIndex + 1);
}
result += "]";//最后别忘记了右括号
return result;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
//首先将data字符串以逗号进行分割
vector<string> dataVec;//data以逗号分隔开
int dataSize = data.size();
//取出中间的数据(null转换为INT_MIN
for (int index = 1; index < dataSize - 1; ++index) {
string tempData = "";
//一直复制,直到遇到逗号
while (index < dataSize - 1 && data[index] != ',') {
tempData += data[index++];
}
dataVec.push_back(tempData);
}
//将层次遍历序列序列化为二叉树
int dataVecSize = dataVec.size();
queue<TreeNode*> myQue;//反序列化的辅助队列
//层次遍历只为空节点的特殊情况
if (dataVec[0] == "null") {
return NULL;
}
TreeNode *result = new TreeNode(atoi(dataVec[0].c_str())), *tempPtr;//根节点,atoi(dataVec[0].c_str()转化为int
myQue.push(result);
for (int index = 1; index < dataVecSize; ++index) {
tempPtr = myQue.front();//获取下一个即将构建的节点
myQue.pop();
//构建左子树
if (dataVec[index] != "null") {
tempPtr->left = new TreeNode(atoi(dataVec[index].c_str()));
myQue.push(tempPtr->left);//记得要放入队列,因为左子树可能还需要构造
}
index += 1;//dataVec指针后移
//构建右子树
if (index < dataVecSize && dataVec[index] != "null") {
tempPtr->right = new TreeNode(atoi(dataVec[index].c_str()));
myQue.push(tempPtr->right);//记得要放入队列,因为右子树可能还需要构造
}
}
return result;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));