《二叉树序列化与反序列化:实现方法与细节解析》

前言

依赖:二叉树遍历算法细节与优化方案
本篇涉及谈谈二叉树的序列化问题。先序后序层序序列化以及反序列化的问题 中序序列化是不行的, 下面会给出解释

  1. 刷题网站:洛谷,leetcode, 牛客网。 网站链接自寻!
  2. 参考: 《程序员代码面试指南》 & 代码随想录。 每道题后我都会附带链接, 代码会上传到GitHub上
  3. 基础部分简略(任意教材都能找到的内容, 初学者都会的内容); 进阶部分有一定思考难度和coding挑战;拓展部分学得更加有深度。 上难度的平衡树有序表(treap, spaly, 红黑树这些)基本不会涉及。
  4. 编程语言: 笔者热爱Java, Java为主, 目前该模块并没有提供其它语言版本。 -借助chatgpt转换成自己的语言吧!
  5. IDE:Intellij IDEA。 主题: MonoKai pro ; 字体: Fira cod light。
  6. 容器和算法技巧: 栈, 队列, 哈希表, 数组; 递归, 分治, 对于部分可以使用动态规划的题也会提供解释。 读者应当可以用数组手搓栈和队列结构

提示

  • 题目通过000~999进行编号, 不过网站暂未提供目录结构无法快速寻找相关题目(不好意思)🥲。
  • 标题可以点击跳转页面。每道题都配有相关链接。 函数题一般是leetcode, acm风格是牛客和洛谷的。 处理输入输出的题的类里多数有main函数可以自行运行测试。
  • 每道题都可以ctrl + c, ctrl + v提交。注意:修改类名, 函数名, 不要提交无关的类。
  • 思考和coding, 而不是注重题量和速度哦。😘

013 先序遍历序列化和反序列化

内存中二叉树结构如何得以保存。 我们知道内存断电(没有任何服务会永远进行)会丢数据。
硬盘可以持久化地保存文件。 如何将二叉树保存在硬盘上呢?
文件是文本内容, 就是一堆字符串。
序列化本质是一种映射关系。只有将二叉树映射出一个字符串, 并且保证字符串能在内存中调用函数还原出这个二叉树, 就可以说是间接保存了这颗二叉树。
二叉树->字符串:称作二叉树的序列化。
字符串->二叉树:称作二叉树的反序列化。

013是根据先序遍历构建的。
序列化反序列化可以根据后序遍历和层序遍历构建对应的字符串。
中序遍历不行, 后面会举例说明。

如何唯一能保证字符串和二叉树结构对应唯一呢?

       A/ \B   C/ \   \D   E   F

先序序列化结果:
A,B,D,#,#,E,#,#,C,#,F,#,

用,作为节点分隔符;用#替代null(或空节点)。

代码:

//注意修改类名->Solution
//测试链接: https://leetcode.cn/problems/serialize-and-deserialize-binary-tree/
public class Coding006_PreorderSerializeAndDeserialize {//不要提交这个类public static class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { val = x; }}// Encodes a tree to a single string.public String serialize(TreeNode root) {//创建一个可变字符串类StringBuilder类// 字符串高效增加元素。StringBuilder builder = new StringBuilder();//辅助调用f(root, builder);return builder.toString();//转String}//public void f(TreeNode root, StringBuilder builder){if(root == null){builder.append("#,");}else {//链式调用builder.append(root.val).append(",");f(root.left, builder);f(root.right, builder);}}//全局变量追踪当前字符public static int cnt = 0;// Decodes your encoded data to tree.public TreeNode deserialize(String data) {//根据分割符","切割字符串 ->字符串数组。String[] vals = data.split(",");cnt = 0;return g(vals);//调用辅助方法}public TreeNode g(String[] vals){//提取当前字符串String cur = vals[cnt++];if(cur.equals("#")){return null;}//递归: 生成当前节点 + 左子树连接递归 + 右子树连接递归。TreeNode head = new TreeNode(Integer.parseInt(cur));head.left = g(vals);head.right = g(vals);return head;//返回最终结果。}
}

014: 后序遍历序列化和反序列化

前置:013先序遍历序列化和反序列化
只需要在013基础上修改一些内容, 就可以得到反序列化的代码了。
序列化过程: 递归构建字符串的过程改成后序顺序。
反序列化过程的根节点应该切割后字符串的最后一个位置, 然后按照右左顺序复原树即可。

注意修改类名->Solution
// 测试链接 : https://leetcode.cn/problems/serialize-and-deserialize-binary-tree/
public class Coding007_PostorderSerializeAndDeserialize {//不要提交这个类public static class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { val = x; }}// Encodes a tree to a single string.public String serialize(TreeNode root) {//创建一个可变字符串类StringBuilder类// 字符串高效增加元素。StringBuilder builder = new StringBuilder();//辅助调用f(root, builder);return builder.toString();//转String}//public void f(TreeNode root, StringBuilder builder){if(root == null){builder.append("#,");}else {f(root.left, builder);f(root.right, builder);builder.append(root.val).append(",");}}//全局变量追踪当前字符public static int cnt = 0;// Decodes your encoded data to tree.public TreeNode deserialize(String data) {//根据分割符","切割字符串 ->字符串数组。String[] vals = data.split(",");cnt = vals.length-1;return g(vals);//调用辅助方法}public TreeNode g(String[] vals){//提取当前字符串String cur = vals[cnt--];if(cur.equals("#")){return null;}TreeNode head = new TreeNode(Integer.parseInt(cur));head.right = g(vals);head.left = g(vals);return head;}
}

015: 层序遍历序列化和反序列化

前置:
013先序遍历序列化和反序列化, 了解序列化和反序列化的概念即可。
008经典层序遍历

看过以上前置, 可以直接阅读代码部分即可

//二叉树的层序序列化和反序列化
public class Coding008_LevelorderSerializeAndDeserialize {//不要提交这个类public static class TreeNode {public int val;public TreeNode left;public TreeNode right;public TreeNode(int v) {val = v;}}//提交这个类1public class Codec {public static int MAX = 10001;public static TreeNode[] queue = new TreeNode[MAX];public static int l,r;public String serialize(TreeNode root){StringBuilder builder = new StringBuilder();if(root != null){builder.append(root.val).append(",");l = r = 0;queue[r++] = root;while(l != r){//这里复用root。root = queue[l++];//经典的bfs操作即可。 只需注意, 如果孩子为空应该以"#,"的形式存入。if(root.left != null){queue[r++] = root.left;builder.append(root.left.val).append(",");}else{builder.append("#").append(",");}if(root.right != null){queue[r++] = root.right;builder.append(root.right.val).append(",");}else{builder.append("#").append(",");}}}return builder.toString();}/*** * @param val 字符串* @return 根据字符串是否为空串返回节点。*/private static TreeNode generate(String val){return val.equals("#") ? null : new TreeNode(Integer.parseInt(val));}public TreeNode deserialize(String data) {if(data.isEmpty()){return null;}//根据分割符","切割字符串String[] vals = data.split(",");int cnt = 0;//记录当前字符串数组的有效值l = r = 0;//重置TreeNode root = generate(vals[cnt++]);queue[r++] = root;while(l != r){//按顺序挨个处理TreeNode cur = queue[l++];//连接左右孩子cur.left = generate(vals[cnt++]);cur.right = generate(vals[cnt++]);//根据cur的左右孩子是否为空决定入队。if(cur.left != null){queue[r++] = cur.left;}if(cur.right != null){queue[r++] = cur.right;}}return root;}}
}

结语

我写写写…

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

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

相关文章

STL关联式容器之RB-tree(红黑树)

AVL-tree之外,另一个颇具历史并被广泛运用的平衡二叉搜索树是RB-tree(红黑树)。所谓RB-tree,不仅是一颗二叉搜索树,而且必须满足一下规则: 1:每个节点不是红色就是黑色 2:根节点为…

电脑系统重装小白教程

​对于很多电脑用户来说,系统出现故障或者需要清理时,重装系统是一项不可避免的操作。但是,对于没有技术基础的小白用户而言,重装系统可能会显得复杂且困难。本文将为您提供一份简洁易懂的电脑系统重装教程,帮助您顺利…

使用Ollama和Open WebUI管理本地开源大模型

Open WebUI和Ollama介绍 Open WebUI 是一个功能丰富且用户友好的自托管 Web 用户界面(WebUI),它被设计用于与大型语言模型(LLMs)进行交互,特别是那些由 Ollama 或与 OpenAI API 兼容的服务所支持的模型。O…

Nmap识别MongoDB 6.0指纹

Nmap识别MongoDB 6.0指纹 朋友反馈一个问题,说使用Nmap扫描MongoDB服务时对于6.0以上的版本默认无法识别到服务版本信息。 如上图所示,对应的VERSION信息是空的,在提示信息中可以看到,官方推荐将指纹信息上传以帮助更新服务指纹&…

向量搜索工具之 Milvus vs. Elastic

在当今数据驱动的世界中,向量数据库因其在处理大规模非结构化数据方面的卓越能力而变得越来越重要。随着数据量的爆炸性增长,如何确保这些数据库在存储和检索数十亿数据点时仍能保持高性能,成为了一个关键挑战。 Milvus和Elasticsearch都是管…

Java中日志采集框架-JUL、Slf4j、Log4j、Logstash

1. 日志采集 日志采集是指在软件系统、网络设备、服务器或其他IT基础设施中自动收集日志文件和事件信息的过程。这些日志通常包含了时间戳、事件类型、源和目标信息、错误代码、用户操作记录等关键数据。日志采集的目的是为了监控系统运行状态、分析系统性能、审计用户行为、故…

每日学习记录003:(C++)unique_ptr和shared_ptr

每日学习记录003:(C)unique_ptr和shared_ptr 在C中,unique_ptr和shared_ptr都是智能指针,它们为动态内存管理提供了更安全、更方便的方式。 一、unique_ptr的特点 (一)独占所有权 unique_pt…

免费实用的图片加水印工具

高度自定义的图片加水印工具 因工作需要和朋友的需求,我基于canvas开发了这款图片加水印工具。 地址:https://potatotools.top/toolsEntrance/pic/ImageWatermark.vue.html 功能亮点 尺寸定制 ,轻松调整水印宽高,精准适配每张图…

数字化工厂 MES 成功之艰:深度剖析与探究

系统集成的复杂性 多源异构系统对接难题 在数字化工厂的建设进程中,MES(制造执行系统)处于核心枢纽地位,需与众多不同来源、不同架构的系统进行集成。企业内部往往早已部署了诸如企业资源计划(ERP)系统、…

kimi 大模型 API 接口实现大模型对话 - python 实现

kimi API接口实现大模型对话 - python 实现,具体代码如下: 注意:api_key 需要kimi官网注册后创建。 from openai import OpenAI if __name__ __main__:client OpenAI(api_key "sk-***********", # $MOONSHOT_API_KEY 官网注册…

服务器被隔离导致无法登录

现象描述 云服务器可能会因安全违规(内容或行为违规)或因 DDoS 攻击被封堵隔离,被隔离的云服务器在控制台显示为 “BANNING” 状态。 云服务器被隔离可能由于该台服务器违反了当前法律法规的要求。您可以通过以下方式查看该台服务器是否处于…

PaddleNLP的环境配置:

PaddleNLP的环境配置: conda create -n paddle—test python3.9conda activate paddle—testpython -m pip install paddlepaddle-gpu2.6.1.post112 -f https://www.paddlepaddle.org.cn/whl/windows/mkl/avx/stable.html(paddle—test) (venv) PS D:\work\论文写…

物联网研究实训室建设方案

一、引言 随着物联网技术的快速发展,其在各个行业的应用越来越广泛,对物联网专业人才的需求也日益增加。为满足这一需求,建设一个符合现代化教学需求的物联网研究实训室,对于提高学生的实践能力和创新能力具有重要意义。本方案旨…

javaweb学习——Day2

JS对象 1、array 定义: var namenew Array(元素列表); var name[元素列表] 访问: name[索引]值 array的属性和方法 length属性,获取数组长度 foreach():遍历数组元素 x.forEach(element > { console.log(element); }); push():…

实战精选|如何使用 OpenVINO™ 在 ElectronJS 中创建桌面应用程序

点击蓝字 关注我们,让开发变得更有趣 作者 | Mikołaj Roszczyk 华沙理工大学物联网工程师 翻译 | 武卓 英特尔 AI 软件布道师 排版 | 吴紫琴 OpenVINO™ 最近,我完成了一个 demo 演示,展示了 OpenVINO™ 在 Node.js 框架中的强大功能。得益于与 Electr…

PyCharm的类型警告: Expected type ‘SupportsWrite[bytes]‘, got ‘BinaryIO‘ instead

记录时使用的PyCharm版本: PyCharm 2024.3 (Professional Edition) Build #PY-243.21565.199, built on November 13, 2024 问题描述 当在PyCharm里使用pickle保存文件, 比如以下代码这样: with open(meta_save_path, wb) as f:pickle.dump(meta, f)会发现PyCharm对此发出类型…

【Docker】快速部署 Pikachu:一个包含常见 Web 安全漏洞的渗透测试练习靶场

系统介绍 Pikachu是一个带有漏洞的Web应用系统,在这里包含了常见的web安全漏洞。 如果你是一个Web渗透测试学习人员且正发愁没有合适的靶场进行练习,那么Pikachu可能正合你意。 Pikachu上的漏洞类型列表如下: Burt Force(暴力破解漏洞) XSS…

vscode 执行 vue 命令无效/禁止运行

在cmd使用命令可以创建vue项目但是在vscode上面使用命令却不行 一、问题描述 在 cmd 中已确认vue、node、npm命令可以识别运行,但是在 vscode 编辑器中 vue 命令被禁止,详细报错为:vue : 无法加载文件 D:\Software\nodejs\node_global\vue.…

【电路笔记 通信】:数字式时分制指令响应型多路传输数据总线 1553协议 289A-97协议

系统及组成 MIL-STD-1553是一种用于航空、航天和军用系统中的多路传输数据总线标准。最初由美国国防部在1973年制定,该标准旨在为军用飞机、导弹和其他嵌入式系统提供可靠的数据通信,现已被广泛应用于航空航天、卫星、舰船、地面车辆以及其他关键任务系统…

npm/cnpm的使用

npm 1、安装npm 前往nodejs官网下载安装node 验证是否安装成功node node -v node安装npm也会安装 npm -v 2、使用npm 1. 初始化项目 在一个项目文件夹中运行: npm init 根据提示输入项目信息(如项目名称、版本号等)。 如果你希望快速初…