基本算法之二叉树的序列化和反序列化

二叉树的序列化和反序列化

作用

由于树结构是二维的,在输入输出时,这样的结构不是很好表示,所以需要使用一种方式将树结构转换成一种易于输入输出的形式表示,同时不失树的结构特性。
把树转换成线性结构单元(如数组)称做序列化,把线性结构单元(如数组)还原成树结构称作反序列化。

代码
#include <bits/stdc++.h>
using namespace std;

// 二叉树结构
typedef struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x),left(NULL),right(NULL) {}
} TreeNode;

//注意:to_string()函数是非标准库中的函数,但是被包含在<bits/stdc++.h>中,由于本人本地IDE的问题无法使用to_string()函数,故自己实现了给函数方法。并未考虑到效率问题。
//作用:将数字由int类型转变成string类型。
string to_string(int num){
    string result;
    stringstream ss;
    ss << num;
    ss >> result;
    return result;
}

// 二叉树的序列化和反序列化类
class SerializeAndDeserialize{
private:
	// 分割函数
	// 作用:将字符串按照某种规则分割成字符串片段
    vector<string> split(string& data,char stop){
        vector<string> result;
        string temp;
        for (int i = 0;i < (int)data.size();++i){
            if (data[i] == stop){
                result.push_back(temp);
                temp = "";
            }
            else temp += data[i];
        }
        return result;
    }
	// 将数字由string类型转换成int类型
    int Str2Int(string& s){
        long num = 0;
        int flag = 1;
        for (int i = 0;i < (int)s.size();++i){
            if (i == 0 && s[i] == '-') {
                flag = -1;
                continue;
            } 
            num = num * 10 + (s[i] - '0');
        }
        return (int)(num * flag);
    }
public:
	// 序列化方法
	// 使用广度优先搜索序列化二叉树
    string serialize(TreeNode *root){
        string data;
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()){
            auto cur = q.front();
            q.pop();
            if (cur != NULL){
                data += (to_string(cur->val) + ',');
                q.push(cur->left);
                q.push(cur->right);
            }
            else data += "NULL,";
        }
        return data;
    }
    // 反序列化方法
    TreeNode* deserialize(string data){
        auto v = split(data,',');
        queue<TreeNode*> q;
        if (v[0] == "NULL") return NULL;
        TreeNode *root = new TreeNode(Str2Int(v[0]));
        q.push(root);
        int i = 1,n = v.size();
        while (i < n){
            if (v[i] != "NULL"){
                TreeNode *temp = new TreeNode(Str2Int(v[i]));
                q.front()->left = temp;
                q.push(temp);
            }
            ++i;
            if (v[i] != "NULL"){
                TreeNode *temp = new TreeNode(Str2Int(v[i]));
                q.front()->right = temp;
                q.push(temp);
            }
            ++i;
            q.pop();
        }
        return root;
    }
};
// 辅助函数
void helper(TreeNode* root,vector<int>& result){
    if (root == NULL) return ;
    helper(root->left,result);
    helper(root->right,result);
    result.push_back(root->val);
    return ;
}
// 后序遍历
vector<int> postorder(TreeNode* root){
    vector<int> result;
    helper(root,result);
    return result;
}

// 主函数
// 测试序列化和反序列化是否成功实现
int main(void){
    string data;
    getline(cin,data);
    // data = "1,2,3,NULL,NULL,4,5,"
    SerializeAndDeserialize f;
    TreeNode *root = f.deserialize(data);
    auto result = postorder(root);
    for (int num : result) cout << num << "  ";
    cout << endl;
    string res = f.serialize(root);
    cout << res << endl;
	return 0;
}
写在最后

二叉树的序列化和反序列化方法是有多种实现方式的,有兴趣的可以自己探索效率更高,思路更简洁的方法。
尽管二叉树的序列化和反序列化方法不属于常用的算法之一,但是该算法实现的功能却是很实用的,值得掌握。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值