序列化和反序列化二叉树 -----前序,中序,后序,层序

news2024/10/5 17:25:04

目录

一.序列化和反序列化

1.什么是序列化和反序列化

二.前序遍历

1.序列化

1.问题分析

2.代码实现

2.反序列化

1.问题分析

2.代码实现

三.后序遍历

1.序列化

1.思路分析

2.代码实现

2.反序列化

1.思路分析

2.代码实现

四.中序遍历

1.序列化

1.思路分析

2.代码实现

2.反序列化

1.思路分析

5.层序遍历

1.序列化

1.思路分析

2.代码实现

2.反序列化

1.思路分析

2.代码实现


一.序列化和反序列化

1.什么是序列化和反序列化

序列化(Serialization)是将对象转化为字节序列的过程,方便数据在网络传输和存储过程中的传递。在序列化过程中,对象的状态信息被转换为可以存储或传输的格式(如字节数组、XML、JSON等),以便在需要时能够将其反序列化为原始对象。序列化可以用于在不同的系统之间传输对象,或者将对象存储到磁盘上等。

反序列化(Deserialization)则是将序列化后的字节流还原成对象的过程,即恢复原始的对象状态信息。在反序列化过程中,可以根据序列化时使用的格式,将字节流转换成原始对象,使得原本序列化的对象状态得以恢复。

序列化和反序列化可以使得对象的状态信息在不同的应用程序或系统之间传输或存储变得更加容易和可靠。

我们这里的序列化就是将树对象转化为字符串,反序列化就是将字符串重新转换为树对象

二.前序遍历

1.序列化

1.问题分析

我们先根据前序遍历将树转换为一个字符串,其实很简单,就是一个前序遍历,加上字符串的拼接操作,例如现在题目有如下要求,根据前序遍历将树转换为字符串,空节点用'#'代替,相邻结点用','分割开

例如上图的二叉树,我们序列化成为字符串应该为{2,1,#,6,#,#,3,#,#}

我们代码其实很好实现,这其实就是前序遍历,到空节点的是后拼接#即可

如果对前序,中序,后序,层序遍历不明白的,推荐看这篇文章的讲解:树的遍历方式(前中后,层序遍历,递归,迭代,Morris遍历)-----直接查询代码_允歆辰丶的博客-CSDN博客

2.代码实现

    //前序遍历序列化
    public String preOrderSerialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        preOrderSerialize(root, sb);
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();

    }

    public void preOrderSerialize(TreeNode root, StringBuilder sb) {
        if (root == null) {
            sb.append("#" + ",");
            return;
        }
        sb.append(root.val + ",");
        preOrderSerialize(root.left, sb);
        preOrderSerialize(root.right, sb);

    }

2.反序列化

1.问题分析

我们如何根据字符串反序列化这棵树呢?其实递归的思路还是参考前序遍历.对于这个字符串data,每个结点都是","进行隔开的,而前序遍历的第一个元素就是根结点(关键也在于找到每一颗子树的根结点),因此我们字符串从前到后遍历,这样一层层的构建结点,然后递归后来的时候进行连接,整个二叉树就构建成功了,看下面这个图会更容易的理解为什么这样进行递归

2.代码实现

    //前序遍历反序列化
    public TreeNode preOrderDeserialize(String data) {
        String[] split = data.split(",");
        return preOrderDeserialize(split);

    }

    int index = 0;

    public TreeNode preOrderDeserialize(String[] nodes) {
        if (index >= nodes.length) {
            return null;
        }
        String node = nodes[index++];
        if (node.equals("#")) {
            return null;
        }
        //根
        TreeNode root = new TreeNode(Integer.parseInt(node));
        //左
        root.left = preOrderDeserialize(nodes);
        //右
        root.right = preOrderDeserialize(nodes);
        return root;

    }

三.后序遍历

1.序列化

1.思路分析

还是这颗二叉树,根据后序遍历的顺序,也是很容易就可以写出代码

这后序遍历序列化的字符串应该为:{#,#,#,6,1,#,#,3,2};

2.代码实现

    //后序遍历序列化
    public String postOrderSerialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        postOrderSerialize(root, sb);
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();

    }

    public void postOrderSerialize(TreeNode root, StringBuilder sb) {
        if (root == null) {
            sb.append("#" + ",");
            return;
        }
        postOrderSerialize(root.left, sb);
        postOrderSerialize(root.right, sb);
        sb.append(root.val + ",");

    }

2.反序列化

1.思路分析

后序遍历的反序列化和前序遍历的反序列化还是有一定的不同的,但大致的思路是一样的,就是寻找根节点的位置,然后递归一步步的建立二叉树,根据后序遍历的特点,我们得知这棵树的根结点在字符串最后的位置,然后将index前移,这个时候我们可以照抄前序遍历反序列化的代码了吗?当然不是,我们根据下面这个图可以很清楚的看到,root结点的前边是右子树的结点,因此我们应该先建立右子树,然后再建立左子树.

2.代码实现

    //后序遍历反序列化
    public TreeNode postOrderDeserialize(String data) {
        String[] split = data.split(",");
        index2 = split.length - 1;
        return postOrderDeserialize(split);

    }

    int index2;

    public TreeNode postOrderDeserialize(String[] nodes) {
        if (index2 < 0) {
            return null;
        }
        String node = nodes[index2--];
        if (node.equals("#")) {
            return null;
        }
        //根
        TreeNode root = new TreeNode(Integer.parseInt(node));
        //左
        root.right = postOrderDeserialize(nodes);
        //右
        root.left = postOrderDeserialize(nodes);
        return root;

    }

四.中序遍历

1.序列化

1.思路分析

和上面两题的思路一样,根据中序遍历的顺序,完成中序遍历的序列化

还是上面的树,中序遍历的序列化答案应该是为:{#,1,#,6,#,2,#,3,#};

2.代码实现

    //中序遍历序列化
    public String infixOrderSerialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        infixOrderSerialize(root, sb);
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();

    }

    public void infixOrderSerialize(TreeNode root, StringBuilder sb) {
        if (root == null) {
            sb.append("#" + ",");
            return;
        }
        infixOrderSerialize(root.left, sb);
        sb.append(root.val + ",");
        infixOrderSerialize(root.right, sb);

    }

2.反序列化

1.思路分析

中序遍历无法进行反序列化,我们在这里可以思考一下原因,在前序遍历和后序遍历的反序列化中,我们最主要的步骤就是找根结点,而在中序遍历的字符串中,我们无法确定根结点的位置,因此我们不能进行反序列化

5.层序遍历

1.序列化

1.思路分析

层序遍历其实就是借助队列来进行序列化,和层序遍历一样,一层一层的,只不过遇到非空节点,我们需要添加到队列中,因为在进行序列化的时候,空节点默认转换为"#",如果出队列的元素为null的时候,我们添加这个元素,并且进行continue操作.

层序遍历的序列化结果为:{2,1,3,#,6,#,#,#,#};

2.代码实现

    public String levelOrderSerialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode pop = queue.pop();
            if (pop == null) {
                sb.append("#" + ",");
                continue;
            }
            sb.append(pop.val + ",");
            queue.offer(pop.left);
            queue.offer(pop.right);

        }
        sb.deleteCharAt(sb.length() - 1);        
        return sb.toString();

    }

2.反序列化

1.思路分析

反序列化的思路其实和序列化的思路还是很想的,每一次找到根结点,然后将左右节点入队列,依次进行下去就可以了.

2.代码实现

    public TreeNode levelOrderDeserialize(String data) {
        String[] nodes = data.split(",");
        if (nodes[0].equals("#")) {
            return null;
        }
        int index = 1;
        TreeNode root = new TreeNode(Integer.parseInt(nodes[0]));
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode parent = queue.pop();
            if (nodes[index].equals("#")) {
                parent.left = null;
            } else {
                parent.left = new TreeNode(Integer.parseInt(nodes[index]));
                queue.offer(parent.left);
            }
            index++;
            if (nodes[index].equals("#")) {
                parent.right = null;
            } else {
                parent.right = new TreeNode(Integer.parseInt(nodes[index]));
                queue.offer(parent.right);

            }
            index++;
        }

        return root;
        
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/413311.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot 使用Prometheus采集自定义指标数据

一、我们需要什么指标 对于DDD、TDD等&#xff0c;大家比较熟悉了&#xff0c;但是对于MDD可能就比较陌生了。MDD是Metrics-Driven Development的缩写&#xff0c;主张开发过程由指标驱动&#xff0c;通过实用指标来驱动快速、精确和细粒度的软件迭代。MDD可使所有可以测量的东…

RPC调用框架简单介绍

一.Thrift Apache Doris目前使用的RPC调度框架。Thrift是一款基于CS&#xff08;client -server&#xff09;架构的RPC通信框架&#xff0c;开发人员可以根据定义Thrift的IDL(interface decription language)文件来定义数据结构和服务接口&#xff0c;灵活性高&#xff0c;支持…

Leetcode.2583 二叉树中的第 K 大层和

题目链接 Leetcode.2583 二叉树中的第 K 大层和 Rating &#xff1a; 1374 题目描述 给你一棵二叉树的根节点 root和一个正整数 k 。 树中的 层和 是指 同一层 上节点值的总和。 返回树中第 k 大的层和&#xff08;不一定不同&#xff09;。如果树少于 k 层&#xff0c;则返…

INFINONE XC164单片机逆向记录(5)C166地址系统

本人所写的博客都为开发之中遇到问题记录的随笔,主要是给自己积累些问题。免日后无印象,如有不当之处敬请指正(欢迎进扣群 24849632 探讨问题); 写在专栏前面https://blog.csdn.net/Junping1982/article/details/129955766 INFINONE XC164单片机逆向记录(1)资料准备

Python爬虫知识回顾

之前一直沉溺于java&#xff0c;jsp&#xff0c;ssh&#xff0c;db等爬虫&#xff0c;现在又要开始走python的老路了。常用的requests库&#xff0c;通过requests对象的get方法&#xff0c;获取一个response对象。jsp的东西。 其中timeout,proxies,headers,cookies,verify,是我…

webgl-画指定颜色三角形

html <!DOCTYPE html> <head> <style> *{ margin: 0px; padding: 0px; } </style> </head> <body> <canvas id webgl> 您的浏览器不支持HTML5,请更换浏览器 </canvas> <script src"./main.js"></script&g…

JUC之CountDownLatch与CyclicBarrier

1.前言 在java.util.concurrent包中为我们提供了很多的线程同步工具类&#xff0c;例如CountDownLatch与CyclicBarrier&#xff0c;那么它们主要的用途是什么呢&#xff1f;且看后续分析。 2.CountDownLatch 2.1 什么是CountDownLatch CountDownLatch&#xff0c;顾名思义&…

从ReentrantLock角度解析AQS

一、概述 闲来不卷&#xff0c;随便聊一点。 一般情况下&#xff0c;大家系统中至少也是JDK8了&#xff0c;那想必对于JDK5加入的一系列功能并不陌生吧。那时候重点加入了java.util.concurrent并发包&#xff0c;我们简称为JUC。JUC下提供了很多并发编程实用的工具类&#xf…

风光及负荷多场景随机生成与缩减

目录 1 主要内容 计算模型 场景生成与聚类方法应用 2 部分程序 3 程序结果 4 程序链接 1 主要内容 该程序方法复现了《融合多场景分析的交直流混合微电网多时间尺度随机优化调度策略》3.1节基于多场景技术的随机性建模部分&#xff0c;该部分是随机优化调度的重要组成部分…

记录-css实现交融文字效果

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 CSS是有魔法的&#xff0c;我们今天来实现一个CSS的动画效果&#xff0c;只需要几行代码就可以搞定。 第一步、我们要将一行文字从中间展开 <!DOCTYPE html> <html lang"en"> &…

面试官:聊聊js原型

一分钟了解原型对象 js分为函数对象和普通对象 &#xff0c;每个对象都有__proto__属性&#xff0c;但是只有函数对象才有prototype属性&#xff0c;prototype属性就是函数的原型对象。 比如说 构造函数通过new 实化一个实例对象&#xff0c;实例对象的__proto__ 指向原型对象…

NumPy 基础知识 :6~10

原文&#xff1a;Numpy Essentials 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 六、NumPy 中的傅立叶分析 除其他事项外&#xff0c;傅立叶分析通常用于数字信号处理。 这要归功于它在将输入信号&#xff08;时域&#xff09;分离为以离散频率&#xff08;频域&am…

Spring Boot集成Druid实现多数据源的两种方式

目录 项目场景&#xff1a; 一、集成com.baomidou的方式 1、maven依赖&#xff1a; 2、 配置文件&#xff1a; 3、 使用注解切换数据源&#xff1a; 二、基于AOP手动实现多数据源原生的方式 1、maven依赖&#xff1a; 2、 配置文件&#xff1a; 3、 多数据源名称类 4…

数字中国理念引领国企人力资源数字化转型与实践

3月初&#xff0c;《数字中国建设整体布局规划》出台&#xff0c;作为中国数字经济发展的重要指导性文件&#xff0c;规划提出了数字中国建设的总体目标和战略方向&#xff0c;文件详细阐述了数字中国内涵&#xff0c;包含数字经济、数字社会、数字政府以及数字生态等内涵。《规…

制造企业该如何选择MES生产管理系统?盘点四大生产管理系统软件

本文将介绍&#xff1a;1、如何选择MES(生产管理系统&#xff09;&#xff1b;2、盘点四款好用的生产管理系统 生产管理系统即MES(Manufacturing Execution System)&#xff0c;制造执行系统。是面向车间生产的管理系统。在产品从工单发出到成品完工的过程中&#xff0c;MES系…

1206. 设计跳表

1206. 设计跳表 不使用任何库函数&#xff0c;设计一个 跳表 。 跳表 是在 O(log(n)) 时间内完成增加、删除、搜索操作的数据结构。跳表相比于树堆与红黑树&#xff0c;其功能与性能相当&#xff0c;并且跳表的代码长度相较下更短&#xff0c;其设计思想与链表相似。 例如&a…

如何收集EMC VPLEX 日志和VPLEX日志的简单解读

对于VPLEX遇到的问题&#xff0c;和二线沟通最快最有效的办法就是收集完整的日志&#xff0c;而不是拍一个照片。本文就详细介绍如何收集日志&#xff1f;和那些日志文件对我们分析问题是有价值的。 命令行ssh登录Vplex 管理控制台&#xff0c;然后进入Vplexcli命令行&#xf…

Windows安装Nginx并配置负载均衡

Nginx简介 Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器&#xff1b;同时也是一个IMAP、POP3、SMTP代理服务器&#xff1b;Nginx可以作为一个HTTP服务器进行网站的发布处理&#xff0c;另外Nginx可以作为反向代理进行负载均衡的实现。 Nginx使用基于事件驱动…

HOJ项目部署(前后端及其判题机)

文章目录HOJ项目部署1 项目准备1.1 拉取HOJ项目到本地1.2 项目包结构解读2 后端部署DataBackup2.1 环境准备1&#xff09;项目基本数据导入2&#xff09;Nacos环境配置2.2 修改配置1&#xff09;修改application-prod.yml2&#xff09;修改bootstrap.yml3&#xff09;修改上传文…

【模板特性补充】

目录&#xff1a;前言一、非类型模板参数使用方法使用场景二、模板特化&#xff08;一&#xff09;函数模板特化&#xff08;二&#xff09;类模板特化1.全特化2.偏特化使用场景三、模板分离编译1. 什么是分离编译2.模板的分离编译3.解决方法四、模板总结前言 打怪升级&#x…