449. Serialize and Deserialize BST

本文探讨如何利用二叉搜索树(BST)的性质进行序列化和反序列化。仅需前序遍历序列即可完成,避免了额外的内存消耗。在反序列化过程中,通过BST的大小关系不断插入节点。注意处理空树情况时,应初始化TreeNode指针以防止非法内存访问。
摘要由CSDN通过智能技术生成

经典题目之一,二叉树的遍历和深度广度优先都相关。
一般的binary tree的serialization 和 deserialization 相对麻烦一点,因为没有多余特征可以利用。但binary search tree就有重要的大小关系可以利用。或者说,binary tree的恢复,往往需要preorder 和inorder两个序列,或者postorder和inorder。但是binary search tree只需要preorder或者postorder就行。只用这俩就是深度优先搜索了。只用level order也行,但不太方便, 因为需要额外的内存消耗,而且本质上也还是深度优先。

方法一:preorder based serialization and deserializaiton

/**
 * 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 {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string res = "";
        serialize_helper(root, res);
        return res;
    }
    void serialize_helper(TreeNode* root, string &res) {
        if (root == NULL) return;
        res += to_string(root->val) + ' ';
        serialize_helper(root->left, res);
        serialize_helper(root->right, res);
        return;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        TreeNode* root = NULL;
        if (data.size() == 0) return root;
        vector<int> num;
        int i = 0;
        string curr;
        while (i < data.size()) {
            curr.clear();
            while (i < data.size() && data[i] != ' ') curr += data[i++];
            num.push_back(stoi(curr));
            i++;
        }
        deserialize_helper(root, num, 0, num.size() - 1);
        return root;
    }
    void deserialize_helper(TreeNode* &root, vector<int> &num, int begin, int end) {
        if (begin > end) return;
        root = new TreeNode(num[begin]);
        int i = begin + 1;
        for ( ; i <= end; i++) {
            if (num[i] > num[begin]) break;
        }
        deserialize_helper(root->left, num, begin + 1, i - 1);
        deserialize_helper(root->right, num, i, end);
    }
};

这里我一开始测试的时候经常在输入为空的时候出现非法内存访问的报错,因为一开始我没有特别初始化TreeNode指针,这个时候如果没有合适的默认初始化,在直接return的情况下就会报错。所以提个醒,所有的指针变量,要么初始化为NULL,要么初始化为同类型变量,不要只是定义然后还放任特殊情况下的直接return。

如果使用level order来传递,其实本质上跟上述方法一致,都是利用二叉树本身性质,但在deserialization的时候还得新建两个数组来把小于根和大于根的分开然后传递,内存消耗很严重,不推荐。

方法二:利用BST本身性质来做deserialization
这是从leetcode讨论区粘贴过来的Java solution. 看个意思就行

public class Codec {
    
    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        recurse(root, sb);
        return sb.toString();
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if(data.isEmpty()) return null;
        
        String[] vals = data.split(" ");
        TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
        for(int i = 1; i < vals.length; i++)
            insert(root, Integer.parseInt(vals[i]));
        return root;
    }
    
    private void recurse(TreeNode root, StringBuilder sb) {
        if(root == null) return;
        
        sb.append(root.val + " ");
        recurse(root.left, sb);
        recurse(root.right, sb);
    }
    
    private void insert(TreeNode root, int val) {
        TreeNode curr = root, parent = null;

        while( curr != null) {
            parent = curr;
            curr = curr.val < val ? curr.right : curr.left;
        }
        
        if(parent.val < val)
            parent.right = new TreeNode(val);
        else
            parent.left = new TreeNode(val);
    }
}

相当于在拿到preorder的输出之后,因为本身是先根排序,又有大小关系,可以利用BST本身性质不断插入的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值