二叉樹的序列化與反序列化
阿新 • • 發佈:2020-09-14
題目來源:https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/ .
按照 Leetcode 的官方習慣,二叉樹的序列化邏輯是根據其「層次遍歷」序列來實現的(參考該文章),因此本文以這種方式來解題。
預備工作
對於反序列化過程,其輸入是一個字串,我們需要將其轉換為 vector<string>
,如 "1,null,2"
需要轉換為 {"1", "null", 2"}
.
vector<string> split(string &data, const string &sep) { size_t l = 0; size_t r = data.find(sep, l); vector<string> result; while (r != string::npos) { result.emplace_back(data.substr(l, r - l)); l = r + sep.length(); r = data.find(sep, l); } if (l < data.length()) result.emplace_back(data.substr(l)); return result; }
對於 vector<string>
中的每個元素,構造一個 API,返回對應的二叉樹節點(包括空節點):
TreeNode *generateNode(const string &s)
{
return s == NIL ? nullptr : new TreeNode(stoi(s));
}
其次,需要 2 個常量(以成員變數的形式存在),NIL
是空節點的符號表示,SEPARATOR
是序列化字串中的分隔符:
const string NIL = "null"; const string SEPARATOR = ",";
層次遍歷實現
- 序列化
與一般的層次遍歷幾乎一樣,唯一不同的地方是:在此處,空節點 nullptr
也進入隊列當中 。
❗ 需要注意的是:最後一層均為葉子節點,因此它們的左右孩子均為 null
,按照 Leetcode 的要求,序列化字串中不包含這些最後一層葉子節點的孩子。
string levelSerialize(TreeNode *root) { if (root == nullptr) return ""; queue<TreeNode *> q; q.push(root); vector<string> result; while (!q.empty()) { auto node = q.front(); q.pop(); if (node != nullptr) { result.emplace_back(to_string(node->val)); q.push(node->left); q.push(node->right); } else result.emplace_back(NIL); } while (result.back() == NIL) result.pop_back(); string str; for (auto &x : result) str += (x + SEPARATOR); if (str.back() == SEPARATOR[0]) str.pop_back(); return "[" + str + "]"; }
- 反序列化
還是是普通的層次遍歷演算法改過來的~
TreeNode *levelDeserialize(string &data)
{
if (data.empty()) return nullptr;
if (data.front() == '[' && data.back() == ']') data = data.substr(1, data.length() - 2);
auto v = split(data, SEPARATOR);
int idx = 0, size = v.size();
auto root = generateNode(v[idx++]);
assert(root != nullptr);
queue<TreeNode *> q;
q.push(root);
while (!q.empty())
{
auto node = q.front();
q.pop();
if (idx < size) node->left = generateNode(v[idx++]);
if (idx < size) node->right = generateNode(v[idx++]);
if (node->left != nullptr) q.push(node->left);
if (node->right != nullptr) q.push(node->right);
}
return root;
}