Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
For example, you may serialize the following tree
1 / \ 2 3 / \ 4 5as
"[1,2,3,null,null,4,5]"
, just the same as
how LeetCode OJ serializes a binary tree
. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.
====================================================================================
题目链接:https://leetcode.com/problems/serialize-and-deserialize-binary-tree/
题目大意:编写一个类,对一个二叉树进行序列化和反序列化,两个函数都只能使用其参数来构建。(序列化的意思就是:使用字符串储存二叉树,反序列化的意思是:使用你存储的字符串来构建原来的二叉树)
思路:序列化的做法有很多种,但是序列化和反序列化要选择一样的构建格式,就跟编码和译码的意思一样。
一般的做法有两种:
1、前序遍历
2、中序遍历
3、层次遍历
一般不会选择后续遍历,因为后序遍历的步骤比较复杂。
我这里选了我感觉最简单的那一种:层次遍历。
具体做法如下:
序列化:
1、用queue实现层次遍历
2、访问当前节点不为空时将该节点的值转成string放入结果中,用逗号‘,’隔开
3、如果当前节点左(右)子树不存在,则用‘n’表示,如果存在,则将该节点左(右)子树push进队列
反序列化:
1、同样用queue实现层次遍历
2、我们已知string中的数值是用逗号‘,’隔开的,而且‘n’表示空,因为每个节点有两个孩子(左右子树),所以我们每次从队列中取出一个节点都要计算它的左右子树。对每一次取值,首先判断当前字符是否为n,如果是n则下一节点(左或右子树)值为空,否则生成下一节点并push进队列
参考代码:
/**
* 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 ans = "" ;
if ( root == NULL )
return ans ;
ans += intToStr ( root -> val ) ;
queue <TreeNode*> q ;
q.push ( root ) ;
while ( !q.empty() )
{
TreeNode* temp = q.front() ;
q.pop() ;
if ( temp -> left )
{
q.push ( temp -> left ) ;
ans += "," ;
ans += intToStr ( temp -> left -> val ) ;
}
else
{
ans += ",n" ;
}
if ( temp -> right )
{
q.push ( temp -> right ) ;
ans += "," ;
ans += intToStr ( temp -> right -> val ) ;
}
else
{
ans += ",n" ;
}
}
return ans ;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
int n = data.size() ;
if ( n == 0 )
return NULL ;
TreeNode* root = new TreeNode ( strToInt ( data ) ) ;
queue <TreeNode*> q ;
q.push ( root ) ;
while ( data.size() )
{
TreeNode* temp = q.front() ;
q.pop() ;
if ( data[0] == 'n' )
{
temp -> left = NULL ;
data.erase ( 0 , 1 ) ;
if ( data.size() && data[0] == ',' )
data.erase ( 0 , 1 ) ;
}
else
{
temp -> left = new TreeNode ( strToInt ( data ) ) ;
q.push( temp -> left ) ;
}
if ( data.size() == 0 )
break ;
if ( data[0] == 'n' )
{
temp -> right = NULL ;
data.erase ( 0 , 1 ) ;
if ( data.size() && data[0] == ',' )
data.erase ( 0 , 1 ) ;
}
else
{
temp -> right = new TreeNode ( strToInt ( data ) ) ;
q.push( temp -> right ) ;
}
}
return root ;
}
private :
string intToStr ( int n )
{
if ( n == 0 )
return "0" ;
if ( n < 0 )
return "-" + intToStr ( -n ) ;
string ans = "" ;
while ( n )
{
ans = char ( n % 10 + '0' ) + ans ;
n /= 10 ;
}
return ans ;
}
int strToInt ( string& s )
{
int n = s.size() , ans = 0 ;
if ( n == 0 )
return 0 ;
if ( s[0] == '-' )
{
s.erase ( 0 , 1 ) ;
return - strToInt ( s ) ;
}
for ( int i = 0 ; i < n ; i ++ )
{
if ( s[i] == ',' )
{
s.erase ( 0 , i + 1 ) ;
return ans ;
}
else
ans = ans * 10 + s[i] - '0' ;
}
s = "" ;
return ans ;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));