力扣297题(序列化二叉树,反序列化二叉树,递归) 前序遍历解法 DFS 层级遍历解法 BFS

https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/solution/shou-hui-tu-jie-gei-chu-dfshe-bfsliang-chong-jie-f/

抄的力扣一位大佬的

基本思想:

(1)序列化:

遍历将各个节点的值放到一个列表中

将列表用join()再变成字符串

(2)反序列化:

确定根节点root,然后遵循前序遍历的结果,递归生成左右子树

具体实现:

几个内置函数

(1)join()

str = "-";
seq = ("a", "b", "c"); # 字符串序列
print str.join( seq );

a-b-c

(2)next()

next(迭代器)

每执行一次,返回迭代器中的下一个项目

只有迭代器才能用next()

(3)iter()

将可迭代对象变成迭代器

https://www.liaoxuefeng.com/wiki/1016959663602400/1017323698112640

(4)split()

按规定字符将字符串分割开

string = "www.gziscas.com.cn"

print(string.split('.'))

['www', 'gziscas', 'com', 'cn']

代码:

def serialize(self, root):
        """Encodes a tree to a single string.

        :type root: TreeNode
        :rtype: str
        """

        def dfs(node):
            if node:
                vals.append(str(node.val))
                dfs(node.left)
                dfs(node.right)
            else:
                vals.append("#")

        vals = []
        dfs(root)
        return ",".join(vals)

    def deserialize(self, data):
        """Decodes your encoded data to tree.
        :type data: str
        :rtype: TreeNode
        """

        def dfs():
            v = next(vals)
            if v == "#":
                return None
            node = TreeNode(int(v))
            node.left = dfs()
            node.right = dfs()
            return node
        vals = iter(data.split(","))
        return dfs()

基本思想:

DFS

前序遍历

具体实现:

序列化:

 递归三步:

1、递归参数以及返回结果

参数:根节点

返回结果:以这个节点为根节点的序列化·

2、递归终止条件

递归到null节点返回

3、单层递归逻辑

递归遍历一棵树,重点关注当前节点,他的自述的遍历交给递归完成

“serialize函数,请帮我分别序列化我的左右子树,我等你返回的结果,再拼接一下。”

力扣297题(序列化二叉树,反序列化二叉树,递归)
前序遍历解法 DFS
层级遍历解法 BFS

反序列化:

力扣297题(序列化二叉树,反序列化二叉树,递归)
前序遍历解法 DFS
层级遍历解法 BFS

递归三步:

1、确定递归参数以及返回值

递归参数:二叉树序列化后的字符串

返回值:当前构建好的root

2、递归终止条件

遍历到‘x’时,代表碰到了空节点,返回null

3、单层递归逻辑

定义函数 buildTree 用于还原二叉树,传入由序列化字符串转成的 list 数组。
逐个 pop 出 list 的首项,构建当前子树的根节点,顺着 list,构建顺序是根节点,左子树,右子树。
如果弹出的字符为 "X",则返回 null 节点。
如果弹出的字符是数值,则创建root节点,并递归构建root的左右子树,最后返回root。

力扣297题(序列化二叉树,反序列化二叉树,递归)
前序遍历解法 DFS
层级遍历解法 BFS

代码:

public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if (root == null) return "X,";
        String leftSerialize = serialize(root.left); //左子树的序列化字符串
        String rightSerialize = serialize(root.right); //右子树的序列化字符串
        return root.val + "," + leftSerialize + rightSerialize;//能递归到的节点都当过根节点
    }
    /*
    public String serialize(TreeNode root) {
        if (root == null) return "X";
        String leftSerialize = serialize(root.left); //左子树的序列化字符串
        String rightSerialize = serialize(root.right); //右子树的序列化字符串
        return root.val + "," + leftSerialize +","+ rightSerialize;
    }
    */


    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
            String[] temp = data.split(",");
            Deque<String> dp = new LinkedList<>(Arrays.asList(temp));
            return buildTree(dp);
        }
        private TreeNode buildTree(Deque<String> dq){
            String s = dq.poll(); //返回当前结点
            if (s.equals("X")) return null;
            TreeNode node = new TreeNode(Integer.parseInt(s));
            node.left = buildTree(dq); //构建左子树
            node.right = buildTree(dq); //构建右子树
            return node;
        }
}

层级遍历解法 BFS

基本思想:

先捋清楚啥是层级遍历就啥也好说了

具体实现:

序列化

力扣297题(序列化二叉树,反序列化二叉树,递归)
前序遍历解法 DFS
层级遍历解法 BFS

和DFS得到的不同,它是一层层的。除了第一个是根节点的值,其他节点值都是成对的,对应左右子节点。

反序列化

力扣297题(序列化二叉树,反序列化二叉树,递归)
前序遍历解法 DFS
层级遍历解法 BFS

依然先转成list数组,用一个指针 cursor 从第二项开始扫描。
起初,用list[0]构建根节点,并让根节点入列。
节点出列,此时 cursor 指向它的左子节点值,cursor+1 指向它的右子节点值。
        如果子节点值是数值,则创建节点,并认出列的父亲,同时自己也是父亲,入列。
   如果子节点值为 'X',什么都不用做,因为出列的父亲的 left 和 right 本来就是 null
可见,所有的真实节点都会在队列里走一遍,出列就带出儿子入列

代码:

public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
         if (root == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();//创建一个放结果的字符串
        Queue<TreeNode> queue = new LinkedList<>();//创建一个队列
        queue.offer(root);//放入待考察的节点
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll(); //考察出列的节点
            if (node == null) {//不是真实节点
                sb.append("X,");
            } 
            else {//是真实节点
                sb.append(node.val + ","); //节点值加入sb
                queue.offer(node.left);//子节点入列,不管是不是null节点都入列
                queue.offer(node.right);
            }
        }
        return sb.toString(); 
    }
    


    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if (data == "") {
            return null;
        }
        //序列化字符串给转为成数组
        Queue<String> nodes = new ArrayDeque<>(Arrays.asList(data.split(",")));
        //获取首项,构建根节点
        TreeNode root = new TreeNode(Integer.parseInt(nodes.poll()));
        //创建一个队列
        Queue<TreeNode> queue = new ArrayDeque<>();
        //根节点推入队列
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll(); //考察出列的节点
            String left = nodes.poll(); // 左儿子
            String right = nodes.poll(); // 右儿子
            if (!left.equals("X")) { // 是真实节点
                node.left = new TreeNode(Integer.parseInt(left)); // 创建左儿子节点,然后认父亲
                queue.add(node.left); //左儿子自己也是父亲,入列
            }
            if (!right.equals("X")) { 
                node.right = new TreeNode(Integer.parseInt(right));
                queue.add(node.right);
            }
        }
        return root;
    }
}