剑指offer 37 二叉树的序列化和反序列化

总结:

二叉树的建立:可通过前序遍历和中序遍历创建一个二叉树

可通过中序遍历和后序遍历创建一个二叉树。

二叉树的序列化:前序遍历,或层序遍历均可。

二叉树的反序列化:前序遍历,或层序遍历均可,但要与序列化方法对应。



设计一个算法,并编写代码来序列化和反序列化二叉树。将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”。

如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列化为一个字符串,并且可以将字符串反序列化为原来的树结构。

样例

给出一个测试数据样例, 二叉树{3,9,20,#,#,15,7},表示如下的树结构:

  3
 / \
9  20
  /  \
 15   7

我们的数据是进行BFS遍历得到的。当你测试结果wrong answer时,你可以作为输入调试你的代码。

你可以采用其他的方法进行序列化和反序列化。


这道题让我们对二叉树进行序列化和去序列化的操作。序列化就是将一个数据结构或物体转化为一个位序列,可以存进一个文件或者内存缓冲器中,然后通过网络连接在相同的或者另一个电脑环境中被还原,还原的过程叫做去序列化。现在让我们来序列化和去序列化一个二叉树,并给了我们例子。这题有两种解法,分别为先序遍历的递归解法和层序遍历的非递归解法。先来看先序遍历的递归解法,非常的简单易懂,我们需要接入输入和输出字符串流istringstream和ostringstream,对于序列化,我们从根节点开始,如果节点存在,则将值存入输出字符串流,然后分别对其左右子节点递归调用序列化函数即可。对于去序列化,我们先读入第一个字符,以此生成一个根节点,然后再对根节点的左右子节点递归调用去序列化函数即可,参见代码如下:

// Recursion
class Codec {
public:
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        ostringstream out;
        serialize(root, out);
        return out.str();
    }
    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        istringstream in(data);
        return deserialize(in);
    }
private:
    void serialize(TreeNode *root, ostringstream &out) {
        if (root) {
            out << root->val << ' ';
            serialize(root->left, out);
            serialize(root->right, out);
        } else {
            out << "# ";
        }
    }
    TreeNode* deserialize(istringstream &in) {
        string val;
        in >> val;
        if (val == "#") return nullptr;
        TreeNode *root = new TreeNode(stoi(val));
        root->left = deserialize(in);
        root->right = deserialize(in);
        return root;
    }
};

层序遍历:代码写的非常好

 1、利用队列,先进先出的特性,对其进行层序遍历。

2、序列化方法要和反序列化方法相同,一个用层序遍历序列化,则要用层序遍历反序列化,否则肯定会出错。

string serialize(TreeNode* root)  
{  
    string seq;  
    queue<TreeNode*> Q;  
    Q.push(root);  
    while(!Q.empty())  
    {  
        TreeNode* cur=Q.front();  
        Q.pop();  
        if(cur==NULL)  
            seq.push_back('#');  
        else  
        {  
            seq.push_back(cur->val);  
            Q.push(cur->left);  
            Q.push(cur->right);  
        }  
    }  
    return seq;  
}  
TreeNode* getNode(string& seq,int p)  
{  
    if(seq[p]=='#')  
        return NULL;  
    else   
    {  
        return new TreeNode(seq[p]);  
    }  
}  
TreeNode* deserialize(string& seq)  
{  
    if(seq.empty()||seq[0]=='#')  
        return NULL;  
    int p=0;  
    TreeNode* root=new TreeNode(seq[p++]);  
    queue<TreeNode*> Q;  
    Q.push(root);  
    while(!Q.empty())  
    {  
        TreeNode* cur=Q.front();  
        Q.pop();  
        cur->left=getNode(seq,p++);  
        cur->right=getNode(seq,p++);  
        if(cur->left)  
            Q.push(cur->left);  
        if(cur->right)  
            Q.push(cur->right);  
    }  
    return root;  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值