当前位置: 首页 > article >正文

每日一题——序列化二叉树

序列化二叉树

  • BM39 序列化二叉树
    • 题目描述
      • 序列化
      • 反序列化
    • 示例
      • 示例1
      • 示例2
    • 解题思路
      • 序列化过程
      • 反序列化过程
    • 代码实现
    • 代码说明
    • 复杂度分析
    • 总结

BM39 序列化二叉树

题目描述

请实现两个函数,分别用来序列化和反序列化二叉树。二叉树的序列化是将二叉树按照某种遍历方式转换为字符串格式,而反序列化则是根据字符串重建出原二叉树。

序列化

二叉树的序列化(Serialize)是指将二叉树转换为字符串,通常我们使用层序遍历的方式将树的节点值逐个保存。在序列化的过程中,用某种符号表示空节点(如#),例如:层序序列化的结果为"{1,2,3,#,#,6,7}"

反序列化

二叉树的反序列化(Deserialize)是指根据序列化后的字符串重建出二叉树。例如,给定序列化字符串"{1,2,3,#,#,6,7}",我们可以重新构造出与原二叉树相同的树结构。

示例

在这里插入图片描述

示例1

输入:

{1,2,3,#,#,6,7}

返回值:

{1,2,3,#,#,6,7}

示例2

在这里插入图片描述

输入:

{8,6,10,5,7,9,11}

返回值:

{8,6,10,5,7,9,11}

解题思路

序列化过程

  1. 使用层序遍历的方式遍历二叉树。
  2. 将每个节点的值转化为字符串,并用#表示空节点。
  3. 将结果以逗号连接形成最终的字符串。

反序列化过程

  1. 将序列化后的字符串按逗号分割。
  2. 按照层序的顺序,逐个构建二叉树的节点。
  3. 使用队列来辅助构建树的结构,按照层序遍历的方式将节点插入到对应的位置。

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义二叉树节点
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};

// 定义队列节点
typedef struct QueueNode {
    struct TreeNode* treeNode;
    struct QueueNode* next;
} QueueNode;

// 定义队列
typedef struct {
    QueueNode* front;
    QueueNode* rear;
} Queue;

// 创建队列
Queue* createQueue() {
    Queue* q = (Queue*)malloc(sizeof(Queue));
    q->front = q->rear = NULL;
    return q;
}

// 判断队列是否为空
int isEmpty(Queue* q) {
    return q->front == NULL;
}

// 入队
void enqueue(Queue* q, struct TreeNode* node) {
    QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));
    newNode->treeNode = node;
    newNode->next = NULL;
    if (q->rear != NULL) {
        q->rear->next = newNode;
    }
    q->rear = newNode;
    if (q->front == NULL) {
        q->front = newNode;
    }
}

// 出队
struct TreeNode* dequeue(Queue* q) {
    if (isEmpty(q)) {
        return NULL;
    }
    QueueNode* temp = q->front;
    struct TreeNode* node = temp->treeNode;
    q->front = q->front->next;
    if (q->front == NULL) {
        q->rear = NULL;
    }
    free(temp);
    return node;
}

// 释放队列
void freeQueue(Queue* q) {
    while (!isEmpty(q)) {
        dequeue(q);
    }
    free(q);
}

// 序列化二叉树
char* Serialize(struct TreeNode* root) {
    if (root == NULL) {
        return "#";
    }
    
    Queue* q = createQueue();
    enqueue(q, root);
    char* result = (char*)malloc(10000 * sizeof(char)); // 假设字符串长度足够
    char* buffer = (char*)malloc(100 * sizeof(char));
    int len = 0;
    
    while (!isEmpty(q)) {
        struct TreeNode* node = dequeue(q);
        if (node == NULL) {
            len += sprintf(result + len, "#,");
        } else {
            len += sprintf(result + len, "%d,", node->val);
            enqueue(q, node->left);
            enqueue(q, node->right);
        }
    }
    
    // 去掉最后一个逗号
    if (len > 0 && result[len - 1] == ',') {
        result[len - 1] = '\0';
    } else {
        result[len] = '\0';
    }
    
    free(buffer);
    freeQueue(q);
    return result;
}

// 反序列化二叉树
struct TreeNode* Deserialize(char* data) {
    if (strcmp(data, "#") == 0) {
        return NULL;
    }
    
    char* token = strtok(data, ",");
    struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val = atoi(token);
    root->left = root->right = NULL;
    
    Queue* q = createQueue();
    enqueue(q, root);
    
    while ((token = strtok(NULL, ",")) != NULL) {
        struct TreeNode* parent = dequeue(q);
        
        if (strcmp(token, "#") != 0) {
            struct TreeNode* leftNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
            leftNode->val = atoi(token);
            leftNode->left = leftNode->right = NULL;
            parent->left = leftNode;
            enqueue(q, leftNode);
        }
        
        token = strtok(NULL, ",");
        if (token == NULL) {
            break;
        }
        
        if (strcmp(token, "#") != 0) {
            struct TreeNode* rightNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
            rightNode->val = atoi(token);
            rightNode->left = rightNode->right = NULL;
            parent->right = rightNode;
            enqueue(q, rightNode);
        }
    }
    
    freeQueue(q);
    return root;
}

代码说明

  1. 队列实现:为了方便按层次遍历二叉树,我们使用队列来存储树的节点。
  2. 序列化函数 Serialize:使用层序遍历对树进行遍历,将节点值加入到结果字符串中。如果节点为空,则用#表示。
  3. 反序列化函数 Deserialize:将序列化后的字符串按逗号分割,依次创建节点并建立左右子树。

复杂度分析

  • 时间复杂度:O(n),其中n是树的节点数。每个节点在序列化和反序列化过程中只被访问一次。
  • 空间复杂度:O(n),需要存储队列中的节点以及序列化后的字符串。

总结

本题考察了二叉树的序列化与反序列化,使用层序遍历来实现序列化和反序列化的方法,保证了在时间和空间复杂度上都能满足要求。这题的整体难度还是不小的,但是最主要的是队列的实现,这个完成,任务就完成一半。至于后面函数的实现,就是研究递归了。


http://www.kler.cn/a/525700.html

相关文章:

  • Github 2025-01-25Rust开源项目日报Top10
  • Python设计模式 - 组合模式
  • ARM嵌入式学习--第十天(UART)
  • 【张雪峰高考志愿填报】合集
  • JVM栈溢出线上环境排查
  • gitee——报错修改本地密码
  • Python3 【集合】水平考试:精选试题和答案
  • 【redis进阶】redis 总结
  • 青少年编程与数学 02-008 Pyhon语言编程基础 07课题、数字
  • deepseek R1 14b硬件要求
  • Hive:struct数据类型,内置函数(日期,字符串,类型转换,数学)
  • SpringBoot 基础特性
  • 精灵图的知识
  • YOLOv8源码修改(4)- 实现YOLOv8模型剪枝(任意YOLO模型的简单剪枝)
  • Pytorch框架从入门到精通
  • 基于springboot+vue的扶贫助农系统的设计与实现
  • SSM开发(六) SSM整合下的CURD增删改查操作(IDEA版)
  • 有效运作神经网络
  • 初阶mysql修炼手册
  • Vue.js 组合函数(Composables)
  • 算法随笔_32: 移掉k位数字
  • 供应链系统设计-供应链中台系统设计(十二)- 清结算中心设计篇(一)
  • C语言中的存储类
  • 安卓(android)音乐播放器【Android移动开发基础案例教程(第2版)黑马程序员】
  • VLLM性能调优
  • WPS怎么使用latex公式?