Serialize and Deserialize Binary Tree
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
5 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.
这个题目的设置条件……我个人认为对C++不是很友好就是了,最后用C解决了,用了一个小小的协议,并使用节点的地址作为唯一标识符来使用。
就我个人对网络那点贫瘠的理解来讲,序列化与反序列化其实就是一个“协议”的问题:根据某个协议将数据编码成一个流发出去,然后再根据协议解析接收到的数据流,完成数据的创建。
在碰到这个题目的之前恰好做了HiHoCoder一个类似的题目,就是还原二叉树的,题目在这里。
两题的思路是一样的:从前序遍历和中序遍历还原整个二叉树。当然本题还可以通过层序来恢复就是了。
然而问题出在:HiHo的用例中,所有的二叉树结点的标识都是唯一的,而LeetCode则不唯一,因此在查找中序序列中的节点的过程是很需注意的。
放上AC代码:
1 | typedef struct TreeNode TreeNode; |
再放上HiHo那个题目的AC代码:
1 | #include <iostream> |
以及,类似,然而却RE了的LeetCode代码,其中的findRootIninOrder()函数是不能用在这里的:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
class Codec {
public:
// 序列化为串
void preOrder(TreeNode* root, string& btree)
{
if (root)
{
btree.push_back((char)(root->val));
preOrder(root->left, btree);
preOrder(root->right, btree);
}
}
void inOrder(TreeNode* root, string& btree)
{
if (root)
{
inOrder(root->left, btree);
btree.push_back((char)(root->val));
inOrder(root->right, btree);
}
}
// 反序列化,实际上就是从前序遍历和后序遍历的结果上把二叉树还原出来
// 这是一个分治法的应用。
int findRootIninOrder(char c, string& midStr)
{
for (int i = 0; i < midStr.length(); ++i)
{
if (midStr[i] == c)
{
return i;
}
}
}
TreeNode* rebuild(int begin, int end, int& index, string& midStr, string& preStr)
{
TreeNode* root = NULL;
if (begin < end)
{
++index;
root = new TreeNode((int)(preStr[index]));
int pos = findRootIninOrder(preStr[index], midStr);
root->left = rebuild(begin, pos - 1, index, midStr, preStr);
root->right = rebuild(pos + 1, end, index, midStr, preStr);
}
else if (begin == end)
{
++index;
root = new TreeNode((int)(preStr[index]));
}
else
{
return NULL;
}
return root;
}
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string btree;
preOrder(root, btree);
inOrder(root, btree);
return btree;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
string preStr;
string midStr;
int btreeSize = data.length() / 2;
preStr = data.substr(0, btreeSize);
midStr = data.substr(btreeSize, btreeSize);
if (preStr.length() == 0)
{
return NULL;
}
int index = -1;
return rebuild(0, btreeSize - 1, index, midStr, preStr);
}
};