[230515 剑指37] 序列化二叉树
一 题目
请实现两个函数,分别用来序列化和反序列化二叉树。
你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
**提示:**输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
示例:
输入:root = [1,2,3,null,null,4,5]
输出:[1,2,3,null,null,4,5]
二 整体思路
这题分为两个部分:把给定的二叉树序列化,和根据给定的序列还原二叉树。
- 把给定的二叉树序列化比较简单,类似二叉树遍历的做法,我们可以求二叉树的前中后序遍历序列;
- 但更关键的是还需要根据序列还原二叉树,这就涉及到了字符串的切割以及如何选择二叉树序列化的顺序(是前序遍历还是中序遍历还是后序遍历)
- 对于字符串的切割,我们可以以空格分隔每个节点的值,使用 C++ 中的 isstringstream 来获取每一个节点值,并且用除数字以外的其它任意字符代表空节点
- 因为构造二叉树首先需要构造根节点,再构造左右孩子,所以我们选择前序遍历,这道题我选择递归的方式对二叉树进行遍历。
三 关键点/重点/难点
这道题的难点在建树时需要对字符串进行切割,我们可以利用 C++ 中的 isstringstream 的优势很好地解决这一点。
四 代码分析
/**
* 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 {
private:
TreeNode* buildTree(istringstream& is) {
string val;
is >> val;
if(val == "x") {
return nullptr;
}
TreeNode *node = new TreeNode(stoi(val));
node->left = buildTree(is);
node->right = buildTree(is);
return node;
}
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
if(root == nullptr) {
return "x";
}
string rootVal = to_string(root->val);
string left = serialize(root->left);
string right = serialize(root->right);
return rootVal + " " + left + " " + right;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
istringstream is(data);
return build(is);
}
};
// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));
(五) 一题多解
无
(六) 知识扩展
C++ 中的 istringstream
istringstream 可以将一个字符串与一个流相关联,从而以流的方式对字符串进行提取,这个特性使 istringstream 在分析输入时非常有用。
基础接口:
- clear():清除流。
- str():获取并设置其内容存在于流中的字符串对象。
- operator <<:将字符串添加到字符串流对象。
- operator >>:从字符串流对象中读取一些内容。
应用:
- 逐单词处理以空格分隔的的字符串
- 将数值转换为字符串并对其进行字符串的处理
// C++ program to demonstrate the
// use of a stringstream to
// convert int to string
#include <iostream>
#include <sstream>
using namespace std;
// Driver code
int main()
{
int val = 123;
// object from the class stringstream
stringstream geek;
// inserting integer val in geek stream
geek << val;
// The object has the value 123
// and stream it to the string x
string x;
geek >> x;
// Now the string x holds the
// value 123
cout << x + "4"<< endl;
return 0;
}
output
1234