• 二叉树的序列化和反序列化


    二叉树的序列化和反序列化

    作者:Grey

    原文地址:

    博客园:二叉树的序列化和反序列化

    CSDN:二叉树的序列化和反序列化

    题目链接见:LeetCode 297. Serialize and Deserialize Binary Tree

    主要思路

    可以用如下三种方式

    第一种方式,先序遍历生成序列化字符串,然后按先序规则再反序列化;

    第二种方式,后序遍历生成序列化字符串,然后按后序规则再反序列化;

    第三种方式,按层遍历生成序列化字符串,然后按层次规则再反序列化。

    注:这里不能用中序方式序列化和反序列化,因为,如果二叉树是如下两棵

    image

    image

    两棵树的中序遍历结果都是[null,a,a,a,null],这样进行反序列化的时候,就无法区分这两棵树了。

    其次,针对任何一棵二叉树,我们需要将一些空的节点补充完整,比如下述二叉树

    image

    其中 b 的左孩子,c 的左孩子,d 的右孩子,都是空节点,我们可以用 null 来表示,但是不能忽略,所以以按层序列化为例,我们将空节点设置为‘#’字符,并用'[]'框住序列化的字符串,然后用逗号分隔节点,所以,上述二叉树

    按层序列化的结果是[a,b,c,#,d,#,e,f,#]

    代码如下

    // 二叉树按层遍历经典实现。
        public static String serialize(TreeNode head) {
            if (head == null) {
                return "[]";
            }
            StringBuilder sb = new StringBuilder("[");
            Queue<TreeNode> queue = new LinkedList<>();
            queue.offer(head);
            while (!queue.isEmpty()) {
                TreeNode node = queue.poll();
                sb.append(node == null ? "#" : String.valueOf(node.val)).append(",");
                if (node != null) {
                    queue.offer(node.left);
                    queue.offer(node.right);
                }
            }
            sb.append("]");
            return sb.toString();
        }
    

    反序列化的方式就是把上述字符串还原成一个二叉树,使用一个队列即可,代码如下:

        // 按层反序列化
        public static TreeNode deserialize(String data) {
            if ("[]".equals(data)) {
                return null;
            }
            data = data.substring(1, data.length() - 2);
            String[] values = data.split(",");
            TreeNode head = new TreeNode(Integer.valueOf(values[0]));
            Queue<TreeNode> queue = new LinkedList<>();
            queue.offer(head);
            int size = 1;
            while (!queue.isEmpty() && size < values.length) {
                TreeNode c = queue.poll();
                c.left = "#".equals(values[size]) ? null : new TreeNode(Integer.valueOf(values[size]));
                size++;
                if (size < values.length) {
                    c.right = "#".equals(values[size]) ? null : new TreeNode(Integer.valueOf(values[size]));
                    size++;
                }
                if (c.left != null) {
                    queue.offer(c.left);
                }
                if (c.right != null) {
                    queue.offer(c.right);
                }
            }
            return head;
        }
    

    先序序列化/反序列化,后序序列化/反序列化方法类似

    // 后序方式序列化 迭代方法
        public static String serialize3(TreeNode head) {
            if (head == null) {
                return "[]";
            }
            // 后序遍历的结果加入栈(可以用递归也可以用迭代)
            Stack<TreeNode> stack1 = new Stack<>();
            Stack<TreeNode> stack2 = new Stack<>();
            stack1.push(head);
            while (!stack1.isEmpty()) {
                TreeNode c = stack1.pop();
                stack2.push(c);
                if (c != null) {
                    stack1.push(c.left);
                    stack1.push(c.right);
                }
            }
            // 栈->字符串
            StringBuilder sb = new StringBuilder("[");
            while (!stack2.isEmpty()) {
                TreeNode node = stack2.pop();
                sb.append(node == null ? "#" : node.val).append(",");
            }
            sb.append("]");
            return sb.toString();
        }
    
        // 后序方式反序列化 迭代方式
        public static TreeNode deserialize3(String data) {
            if ("[]".equals(data)) {
                return null;
            }
            String[] values = data.substring(1, data.length() - 2).split(",");
            Stack<String> stack = new Stack<>();
            for (String value : values) {
                stack.push(value);
            }
            return posDerial(stack);
        }
    
        private static TreeNode posDerial(Stack<String> stack) {
            String s = stack.pop();
            if ("#".equals(s)) {
                return null;
            }
            TreeNode root = new TreeNode(Integer.valueOf(s));
            root.right = posDerial(stack);
            root.left = posDerial(stack);
            return root;
        }
    
        // 先序方式序列化 迭代做法
        // 头 左 右
        public static String serialize2(TreeNode head) {
            if (head == null) {
                return "[]";
            }
            StringBuilder sb = new StringBuilder("[");
            Stack<TreeNode> queue = new Stack<>();
            queue.push(head);
            while (!queue.isEmpty()) {
                TreeNode c = queue.pop();
                sb.append(c == null ? "#" : c.val).append(",");
                if (c != null) {
                    queue.push(c.right);
                    queue.push(c.left);
                }
            }
            sb.append("]");
            return sb.toString();
        }
    
        // 先序反序列化
        public static TreeNode deserialize2(String data) {
            if ("[]".equals(data)) {
                return null;
            }
            String[] values = data.substring(1, data.length() - 2).split(",");
            Queue<TreeNode> queue = new LinkedList<>();
            for (String value : values) {
                queue.offer("#".equals(value) ? null : new TreeNode(Integer.valueOf(value)));
            }
            return preDesrial(queue);
        }
    
        private static TreeNode preDesrial(Queue<TreeNode> queue) {
            TreeNode node = queue.poll();
            if (node == null) {
                return null;
            }
            node.left = preDesrial(queue);
            node.right = preDesrial(queue);
            return node;
        }
    

    更多

    算法和数据结构笔记

  • 相关阅读:
    docker的核心概念和安装
    kettle在centos7下部署分布式集群
    Kettle在windows下分布式集群的搭建
    笔记本 原来win10系统改装win7系统遇到 invaid signature detected.check secure boot policy setup问题
    docker 在window10下的安装
    docker 在windows7 、8下的安装
    初识Docker
    MySql 外键约束 之CASCADE、SET NULL、RESTRICT、NO ACTION分析和作用
    学习前端框架Metronic
    Java中的动态代理是什么
  • 原文地址:https://www.cnblogs.com/greyzeng/p/16789819.html
Copyright © 2020-2023  润新知