LintCode-7: Serialize and Deserialize Binary Tree 二叉树序列化和反序列化

本文介绍了一种实现二叉树序列化和反序列化的算法,使用BFS和前序遍历两种方法,提供了详细的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description
Design an algorithm and write code to serialize and deserialize a binary tree. Writing the tree to a file is called ‘serialization’ and reading back from the file to reconstruct the exact same binary tree is ‘deserialization’.

There is no limit on how to serialize or deserialize a binary tree,you just need to ensure the binary tree can be serialized to a string,and the string can be deserialized to original binary tree.

There is no limit of how you deserialize or serialize a binary tree, LintCode will take your output of serialize as the input of deserialize, it won’t check the result of serialize.

Example
Example 1:

Input:

tree = {3,9,20,#,#,15,7}
Output:

{3,9,20,#,#,15,7}
Explanation:

Binary tree {3,9,20,#,#,15,7}, denote the following structure:

3
/ \
9 20
/ \
15  7

it will be serialized {3,9,20,#,#,15,7}

Example 2:

Input:

tree = {1,2,3}
Output:

{1,2,3}
Explanation:

Binary tree {1,2,3}, denote the following structure:

1
/ \
2 3

it will be serialized {1,2,3}

这题感觉比较难,却又是最常考的题目。以后需要仔细回顾。有两种解法:1)BFS 2)前逆遍历递归

解法1:BFS。参考了网上的一些解法。

代码如下:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */


class Solution {
public:
    /**
     * This method will be invoked first, you should design your own algorithm 
     * to serialize a binary tree which denote by a root node to a string which
     * can be easily deserialized by your own "deserialize" method later.
     */
    string serialize(TreeNode * root) {
        if (!root) return "{}";

        string str="{";
        queue<TreeNode *> q;
        q.push(root);

        while(!q.empty()) {
            TreeNode* tempNode=q.front();
            q.pop();
            if (tempNode) {
                str+=to_string(tempNode->val);
                str+=",";
                if (tempNode->left) {
                    q.push(tempNode->left);
                }
                else {
                    q.push(NULL);
                }    
                
                if (tempNode->right) {
                    q.push(tempNode->right);
                }
                else {
                    q.push(NULL);
                }
            } else {
                str+="#,";
            }
        }
        str+="}";
        return str;
    }

    /**
     * This method will be invoked second, the argument data is what exactly
     * you serialized at method "serialize", that means the data is not given by
     * system, it's given by your own serialize method. So the format of data is
     * designed by yourself, and deserialize it here as you serialize it in 
     * "serialize" method.
     */
    TreeNode * deserialize(string &data) {
        if (data=="{}") {
            return NULL;
        }
        
        vector<string> vals=split(data.substr(1, data.size()-2), ",");
        TreeNode* root = new TreeNode(stoi(vals[0]));
        queue<TreeNode *> q;
        q.push(root);
        
        for (int i=1; i<vals.size(); ++i) {
           TreeNode* node=q.front();
           q.pop();
           if (vals[i]!="#") {
               node->left=new TreeNode(stoi(vals[i]));
               q.push(node->left);
            }
            i++;
            if (vals[i]!="#") {
                node->right=new TreeNode(stoi(vals[i]));
                q.push(node->right);
            }
        }
        
        return root;
   }
   
private:
    vector<string> split(const string &str, string delim) {
        vector<string> results;
        int lastIndex = 0, index;
        while ((index = str.find(delim, lastIndex)) != string::npos) {
            results.push_back(str.substr(lastIndex, index - lastIndex));
            lastIndex = index + delim.length();
        }

        if (lastIndex != str.length()) {
            results.push_back(str.substr(lastIndex, str.length() - lastIndex));
        }
        return results;
    }
   
};

注意:
1) Serialize的时候是相当于标准的BFS分层遍历,需要加while(!q.empty())。Deserialize的时候用的for循环遍历vals数组。这里为什么不用while(!q.empty())还没想通。欢迎留言指教。

解法2:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */


class Solution {
public:
    /**
     * This method will be invoked first, you should design your own algorithm 
     * to serialize a binary tree which denote by a root node to a string which
     * can be easily deserialized by your own "deserialize" method later.
     */
 string serialize(TreeNode * root) {
       string res;
       queue<TreeNode *> q;
       q.push(root);
       while(!q.empty()) {
           TreeNode *frontNode = q.front();
           q.pop();
           if (frontNode) {
               res += to_string(frontNode->val) + " ";
           } else {
               res += "# ";
               continue;
           }

           if (frontNode->left) {
               q.push(frontNode->left);
           } else {
               q.push(NULL);
           }

           if (frontNode->right) {
               q.push(frontNode->right);
           } else {
               q.push(NULL);
           }
       }
       return res;
    }
    
    /**
     * This method will be invoked second, the argument data is what exactly
     * you serialized at method "serialize", that means the data is not given by
     * system, it's given by your own serialize method. So the format of data is
     * designed by yourself, and deserialize it here as you serialize it in 
     * "serialize" method.
     */
    TreeNode * deserialize(string &data) {
       
       int len = data.size();
       
       stringstream ss(data);
       string token;
       vector<string> tokens;
       while (ss >> token) tokens.push_back(token);

       queue<TreeNode *> q;
       int pos = 0;
       if (tokens[pos] == "#") return NULL;
       TreeNode *root = new TreeNode(stoi(tokens[pos++]));
       q.push(root);       

       while (!q.empty()) {
           TreeNode *frontNode = q.front();
           q.pop();
           
           if (frontNode && pos < len) {
               if (tokens[pos] != "#") {
                   frontNode->left = new TreeNode(stoi(tokens[pos]));
                   q.push(frontNode->left);
               } else {
                   q.push(NULL);
               }
               pos++;
           }
           
           if (frontNode && pos < len) {
               if (tokens[pos] != "#") {
                   frontNode->right = new TreeNode(stoi(tokens[pos]));
                   q.push(frontNode->right);
               } else {
                   q.push(NULL);
               }
               pos++;
           }
           
       }
       return root;       
    }
};


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值