算法挑战27: 二叉树的序列化与反序列化

3 阅读2分钟

思路:

序列化就是将二叉树变成字符串,可以在不同的编程语言系统中传递

反序列化就是将序列化的字符串重新构建成二叉树数据结构

为了确定唯一的二叉树,不可以用中序遍历结果,因为根节点在数组中间,无法确认根节点的位置

如果是前序遍历的话,根节点就是第一个元素

我们可以用前序遍历的特点来序列化二叉树

既然我们用前序遍历的方式来进行序列化,那么我们反序列化时也需要用同样的方式来进行反序列化

对了,我们知道,遍历分两种,层序遍历和递归遍历

这里我们使用递归前序遍历


序列化

先定义一个数组res,来储存每个节点的值,最后我们把元素拼接起来

每次前序遍历到一个节点时,判断是不是空节点

如果是空节点,我们在res中追加一个特殊字符,可以用"#","null",这里用的null

不是空节点的话, 在res中追加这个节点的值,并且递归它的左右子树

最后用join(",")来拼接成字符串


反序列化

我们拿到的是二叉树序列化的结果,是个字符串

我们可以用split(",")分割成数组values

然后我们遍历这个数组,但是我们要用递归的方式,因为我们是从前往后遍历的

为了实现对数组的遍历,我们必须维护一个递增的索引index

然后在递归函数里面,前序的位置进行判断,是否为"null"

如果是,说明这是一个空节点,我们直接返回null

不是的话,我们构建一个新节点,值就是values[index]

注意,不管是不是空节点,每遍历一个数组元素,就给index++

然后把当前节点的左右子树构建出来,使用dfs

返回当前节点

/**

 * Encodes a tree to a single string.

 *

 * @param {TreeNode} root

 * @return {string}

 */

var serialize = function (root) {
    //数组
    let res = [];
    //递归函数
    function dfs(root) {
        //如果节点是空节点
        if (!root) {
            res.push("null");
            return;
        } else {
            res.push(root.val);
            dfs(root.left);
            dfs(root.right);
        }
    }
        dfs(root);
        return res.join(",");//返回字符串
};

  


/**

 * Decodes your encoded data to tree.

 *

 * @param {string} data

 * @return {TreeNode}

 */

var deserialize = function (data) {
    //非空判断
    if (!data) return null;
    
    //序列化数组
    const values = data.split(",");

    //遍历这个序列化数组
    let index = 0;//维护索引
    function dfs() {
        const val = values[index];
        index++;
        if (val === "null") return null;
        //不是空节点
        //构建根节点
        const root = new TreeNode(Number(val));
        //递归左右子树
        root.left = dfs();
        root.right = dfs();
        //返回当前节点
        return root;
    }
    return dfs();

};