剑指Offer37.序列化二叉树 C++

news2025/1/17 22:59:21

1、题目描述

  • 请实现两个函数,分别用来序列化和反序列化二叉树。
  • 你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
  • 提示:输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
    示例:
    在这里插入图片描述
    输入:root = [1,2,3,null,null,4,5]
    输出:[1,2,3,null,null,4,5]

2、VS2019上运行

方法一:使用深度优先搜索

#include <iostream>
#include <cstring>
#include <string>
#include <list>

using namespace std;

// 二叉树节点的定义
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

// 序列化和反序列化二叉树的类
class Codec {
public:
    // 辅助函数:序列化二叉树
    void rserialize(TreeNode* root, string& str) {
        if (root == nullptr) {
            str += "None,";  // 空节点用"None"表示
        }
        else {
            str += to_string(root->val) + ",";  // 将节点值转化为字符串,并添加到str中
            rserialize(root->left, str);  // 递归序列化左子树
            rserialize(root->right, str);  // 递归序列化右子树
        }
    }

    // 序列化二叉树,并返回序列化后的字符串
    string serialize(TreeNode* root) {
        string ret;//存储序列化后的二叉树字符串的结果
        rserialize(root, ret);
        return ret;
    }

    // 辅助函数:反序列化二叉树
    TreeNode* rdeserialize(list<string>& dataArray) {
        //处理空节点,确保在处理当前节点的值后,链表中的下一个元素就是下一个节点的值。
        if (dataArray.front() == "None") {
            dataArray.erase(dataArray.begin());
            return nullptr;  // 空节点返回nullptr
        }

        TreeNode* root = new TreeNode(stoi(dataArray.front()));  // 创建当前节点
        //stoi用于将第一个元素的字符串表示转换为整数值
        dataArray.erase(dataArray.begin());
        root->left = rdeserialize(dataArray);  // 递归反序列化左子树
        root->right = rdeserialize(dataArray);  // 递归反序列化右子树
        return root;
    }

    // 从输入字符串中反序列化二叉树,并返回根节点
    TreeNode* deserialize(string data) {
        list<string> dataArray;//存储从序列化字符串中解析出的节点值
        string str;//临时存储当前节点的值
        for (auto& ch : data) {//遍历序列化字符串 data 中的每个字符 ch

            //如果当前字符 ch 是逗号 ‘,’,则表示当前节点值的结束。
            //此时,将当前的节点值 str 存储到 dataArray 链表中,并清空 str 以准备解析下一个节点的值。
            if (ch == ',') {
                dataArray.push_back(str);  // 用逗号分割字符串,并将每个节点值存储在链表中
                str.clear();
            }
            else {
                str.push_back(ch);  // 构建当前节点的值
            }
        }
        //处理最后一个节点值
        if (!str.empty()) {
            dataArray.push_back(str);  // 将最后一个节点的值存储在链表中
            str.clear();
        }
        return rdeserialize(dataArray);
    }
};

// 测试序列化和反序列化函数
int main() {
    // 创建一个二叉树
    TreeNode* root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->right->left = new TreeNode(4);
    root->right->right = new TreeNode(5);

    // 创建Codec类的实例
    Codec codec;

    // 序列化二叉树
    string serialized = codec.serialize(root);
    cout << "序列化后的二叉树字符串: " << serialized << endl;

    // 反序列化二叉树
    TreeNode* deserialized = codec.deserialize(serialized);

    // 打印反序列化后的二叉树节点的值
    if (deserialized != nullptr) {
        cout << "反序列化后的二叉树节点值: " << endl;
        cout << deserialized->val << endl;
        cout << deserialized->left->val << " " << deserialized->right->val << endl;
        cout << deserialized->right->left->val << " " << deserialized->right->right->val << endl;
    }
    else {
        cout << "反序列化后的二叉树为空" << endl;
    }

    // 释放分配的内存,清理二叉树
    delete root->right->left;
    delete root->right->right;
    delete root->left;
    delete root->right;
    delete root;

    return 0;
}

序列化后的二叉树字符串: 1,2,None,None,3,4,None,None,5,None,None,
反序列化后的二叉树节点值:
1
2 3
4 5

3、解题思路

  • 序列化:
    1.serialize 函数接受一个二叉树的根节点 root,将二叉树转换为一个字符串。
    2.rserialize 函数是一个递归函数,用于遍历二叉树。它首先将当前节点的值加入到字符串 str 中,如果当前节点为空,则将字符串 “None” 加入到 str 中;否则,将当前节点的左子树和右子树递归地进行序列化。
    3.最后,serialize 函数返回生成的字符串 ret,即二叉树的序列化结果。
  • 反序列化:
    1.deserialize 函数接受一个字符串 data,将其转换为二叉树。
    2.rdeserialize 函数是一个递归函数,用于重构二叉树。它首先检查当前节点值是否为 “None”,如果是则返回空指针;否则,创建一个新的节点,将节点值赋给它,并递归地构建左子树和右子树。
    3.deserialize 函数首先将输入字符串 data 按照逗号进行拆分,构成一个字符串链表 dataArray。然后,调用 rdeserialize 函数,并将 dataArray 作为参数传入,来重建二叉树。
    4.最后,deserialize 函数返回重建的二叉树的根节点。
  • 通过 serialize 函数可以将二叉树转换为字符串,而 deserialize 函数可以将字符串恢复为原始的二叉树结构。

4、序列化和反序列化

  • 序列化:将二叉树在内存中的表示形式转换为字符串
  • 反序列化:将字符串还原为二叉树的内存表示形式

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

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

相关文章

利用css动画和定时器setTimeout,实现上传图片进度条

思路 利用css动画和js定时器&#xff08;setTimeout&#xff09;&#xff0c;实现简单的进度条。 优势 不使用 setInterval&#xff0c;减少js代码量&#xff0c;业务代码更加简洁。 示意图 上传中上传成功上传失败 代码 html <!-- img-wrap有两种状态&#xff1a;u…

【O2O领域】Axure外卖订餐骑手端APP原型图,外卖配送原型设计图

作品概况 页面数量&#xff1a;共 110 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;外卖配送、生鲜配送 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 本品为外卖订餐骑手端APP原型设计图&#x…

以太网(一):PoE供电

一、定义&#xff1a; PoE系统包括供电端设备&#xff08;PSE&#xff09;和受电端设备&#xff08;PD&#xff09;两部分PoE&#xff08;Power over Ethernet&#xff09;&#xff1a;​是一种可以在以太网中透过双绞线来传输电力与数据到设备上的技术PSE&#xff08;Power S…

ROS局部路径规划器插件teb_local_planner规划流程概括总结

本部分文章主要用于对ROS局部路径规划器插件teb_local_planner的规划流程进行梳理&#xff0c;并概括总结&#xff0c;本部分计划包含5~6篇文章&#xff0c;各文章主要内容如下&#xff1a; ☆第一篇&#xff1a;主要介绍ROS导航包Navigation中的 Movebase节点中的路径规划的相…

1000元到3000元预算的阿里云服务器配置大全

1000元、2000元或3000元预算能够买的阿里云服务器配置有哪些&#xff1f;可以选择ECS通用算力型u1云服务器、ECS计算型c7或通用型g7实例规格&#xff0c;当然&#xff0c;如果选择轻量应用服务器的话&#xff0c;更省钱&#xff0c;阿里云百科分享1000-3000元预算能买的阿里云服…

敏捷项目管理解决方案

Leangoo领歌是一款永久免费的专业敏捷研发管理工具&#xff0c;提供敏捷研发解决方案&#xff0c;解决研发痛点&#xff0c;打造成功产品。帮助团队实现需求、迭代、缺陷、任务、测试、发布等全方位研发管理。 敏捷产品路线图管理&#xff1a; 产品路线图是一个高层次的战略计…

Android 9.0 Vold挂载流程解析(下)

Android 9.0 Vold挂载流程解析&#xff08;上&#xff09; 前言 上一篇介绍了Android 文件系统中Vold挂载机制的总体框架&#xff0c;我们分析了vod进程的main.cpp.接下来我们分析下存储卡挂载和卸载的流程。 存储卡挂载 在上篇文章文章提到&#xff0c;监听驱动层挂载和卸…

SOLIDWORKS 2023中装配体配合的正确使用方法 硕迪科技

-SOLIDWORKS 装配体打开时是由不同的阶段和性能检查组成的。如果在创建装配体时未应用基本的配合方法&#xff0c;问题会随着时间的推移而累积&#xff0c;并且在使用时会出现明显的速度减慢。 如果您的装配体运行速度很慢&#xff0c;则很可能是在创建配合时出现了不良操作的症…

腾讯云 CODING 荣获 TiD 质量竞争力大会 2023 软件研发优秀案例

点击链接了解详情 8 月 13-16 日&#xff0c;由中关村智联软件服务业质量创新联盟主办的第十届 TiD 2023 质量竞争力大会在北京国家会议中心召开。本次大会以“聚焦数字化转型 探索智能软件研发”为主题&#xff0c;聚焦智能化测试工程、数据要素、元宇宙、数字化转型、产融合作…

Python入门--变量

变量是指在程序运行期间可以改变其值的数据类型。在Python中&#xff0c;变量可以指定任何数据类型&#xff0c;如字符串、整数、浮点数等。 要创建一个变量&#xff0c;我们必须先指定变量的名称&#xff0c;然后将其赋值。在Python中&#xff0c;变量名可以是任何有意义的名…

分布式基础

1、分布式简介 1.1、分布式定义 分布式系统是一个硬件或软件组件分布在不同的网络计算机上&#xff0c;彼此之间仅仅通过消息传递进行通信和协调的系统。 1.2、分布式特点 分布性&#xff1a;分布式系统中的多台计算机都会在空间上随意分布&#xff0c;同时&#xff0c;机器…

本地访问远程web服务

1、 2、以管理员身份运行cmd ssh usernameremote_address -L 127.0.0.1:8888:127.0.0.1:8008 3、在远程服务器上去运行web服务 4、本地访问

【BASH】回顾与知识点梳理(三十六)

【BASH】回顾与知识点梳理 三十六 三十六. 认识与分析登录档36.1 什么是登录档CentOS 7 登录档简易说明登录档的重要性Linux 常见的登录档档名登录档所需相关服务 (daemon) 与程序CentOS 7.x 使用 systemd 提供的 journalctl 日志管理 登录档内容的一般格式 36.2 rsyslog.servi…

C++中String的语法及常用接口用法

在C语言中&#xff0c;string是一个标准库类&#xff08;class&#xff09;&#xff0c;用于处理字符串&#xff0c;它提供了一种更高级、更便捷的字符串操作方式&#xff0c;string 类提供了一系列成员函数和重载运算符&#xff0c;以便于对字符串进行操作和处理。 一、string…

大模型系列|基于大模型的聊天助手案例(三)

大模型系列&#xff5c;垂直大模型的几种训练策略&#xff08;一&#xff09; 大模型系列&#xff5c;基于大模型复杂数据系统架构&#xff08;二&#xff09; 本篇主要是采集一些大模型在聊天机器人中的案例&#xff0c;因为目前很多企业都会考虑将LLM与业务结合&#xff0c;L…

LSTM网络模型:从基础到应用播

目录 介绍 LSTM的基础结构 LSTM的训练方法 LSTM的应用场景 总结 LSTM&#xff08;Long Short-Term Memory&#xff09;网络模型是一种递归神经网络&#xff0c;被广泛应用于自然语言处理、语音识别、图像处理等领域。本文将从LSTM的基础结构、训练方法、应用场景等方面进行…

LD_RPELOAD环境变量

目录 LD_RPELOAD环境变量 LD_RPELOAD 定义 程序的连接方式 Linux规定动态链接库的文件名规则如下 动态链接库的搜索路径搜索的先后顺序 LD_RPELOAD的劫持 demo 1.定义一个hook.c文件 2.将所写的hook.c 文件编译为动态链接库hook.so 3.劫持检测&#xff0c;查看LD_PREL…

于vue3+vite+element pro + pnpm开源项目

河码桌面是一个基于vue3viteelement pro pnpm 创建的monorepo项目&#xff0c;项目采用的是类操作系统的web界面&#xff0c;操作起来简单又方便&#xff0c;符合用户习惯&#xff0c;又没有操作系统的复杂&#xff01; 有两个两个分支&#xff0c;一个是web版本&#xff0c;…

DDD诊所——聚合过大综合症

“DDD诊所”是Thoughtworks DDD社区的一项活动&#xff0c;通过对同事们在实施DDD过程中遇到的问题进行分析和解答&#xff0c;共同提高开发水平。我们将其中一些典型案例整理成文供大家参考。之后也会考虑在适当的时候将这一形式对外部开放。 就诊日期&#xff1a;2022年6月8…

基于SpringBoot的在线视频教育平台的设计与实现【附ppt|开题|万字文档(LW)和搭建文档】

主要功能 前台界面&#xff1a; ①首页、课程信息推荐、课程信息展示、查看更多等 ②课程信息类型、课程名称、关键词、教师姓名等 ③添加购物车、立即购买、评论、点我收藏、视频播放等 ④个人中心、我的订单、我的地址、我的收藏、客服等 后台登录&#xff1a; ①首页、个人…