首页 > 其他分享 >二叉树的序列化和反序列化

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

时间:2022-10-13 21:44:10浏览次数:69  
标签:null TreeNode queue 二叉树 new return 序列化

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

作者: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;
    }

更多

算法和数据结构笔记

标签:null,TreeNode,queue,二叉树,new,return,序列化
From: https://www.cnblogs.com/greyzeng/p/16789819.html

相关文章

  • PHP Phar反序列化学习
    PHPPhar反序列化学习PharPhar是PHP的压缩文档,是PHP中类似于JAR的一种打包文件。它可以把多个文件存放至同一个文件中,无需解压,PHP就可以进行访问并执行内部语句。默认开......
  • 算法练习-第十七天【二叉树】
    二叉树110.平衡二叉树参考:代码随想录思路二叉树的深度:从根节点出发到该节点的最长简单路径边的条数。二叉树的高度:从该节点出发到叶子节点的最长简单路径的条数。题......
  • java反序列化漏洞及其检测
    1java反序列化简介java反序列化是近些年安全业界研究的重点领域之一,在ApacheCommonsCollections、JBoss、WebLogic等常见容器、库中均发现有该类漏洞,而且该类型漏洞容......
  • C#中使用Newtonsoft.Json序列化和反序列化自定义类对象
    C#中使用Newtonsoft.Json序列化和反序列化自定义类对象在C#中序列化和反序列化自定义的类对象是比较容易的,比如像下面的一个Customer类,privateclassCustomer{......
  • Java 序列化
    importjava.io.*;/***Java序列化*Java提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存......
  • 计算二叉树中度为二的结点个数
    计算度为二的结点个数递归法(一)算法思想:用递归的数学模型来理解:f(b)=0//若b是空树则本身不是度为二的结点,也无左右孩子,总共的度为二结点......
  • 交换二叉树的所有左右子树
    递归方式交换所有子树递归思想:把一个复杂问题抽象化,在用调用自身的方式求解问题算法思想:把一颗二叉树抽象成一个根结点和左右子结点,先交换左孩子的左右子树,再交换右孩......
  • LeetCode 二叉树遍历算法题解 All In One
    LeetCode二叉树遍历算法题解AllInOne树的遍历/TreeTraversal主要看根节点Root的遍历顺序:前,中,后前序遍历(Root,Left,Right)先访问根节点,然后遍历左......
  • 算法练习-第十六天【二叉树】
    二叉树的深度与高度二叉树的深度:从根节点到该节点的最长简单路径边的条数或节点数(取决于深度是否从1开始)二叉树的高度:从该节点到叶子节点的最长简单路径边的条数或节点数......
  • //按照完全二叉树的层次顺序一次输入节点信息建立二叉链表的算法
    //按照完全二叉树的层次顺序一次输入节点信息建立二叉链表的算法#include<stdio.h>#include<stdlib.h>typedefcharDataType;typedefstructnode{DataT......