丑陋的二叉树序列化与反序列化

一 前言

本宝宝好好的上午,本来打算把操作系统的视频刷两章,然后看到labuladong大佬更新微信文章了,忍不住看了一把,一般我是不看的,因为看不懂啊,我好菜啊。但是,今天我忍不住点开了,一看,二叉树的序列化与反序列化,这个东东是啥啊。二叉树,我学过哎,我可以。

然后看了下,发现

  • 二叉树的序列化就是:将一颗二叉树,转换成一维的序列。
  • 二叉树的反序列化就是:从一维的序列,生成一颗二叉树。

感觉,我可以做哎。然后看了下代码,emmmm,作为一个只会C,C++的特性基本不会啥的菜鸡,咦,也能看懂。但是我不懂序列啊,我能不能用数组做个简单的,不用字符串啥的,序列啥的,然后就开干。试一试。

试的时候,结合着我瞎整的3w字数据结构笔记和labuladong大佬的文章,编了下,咦,我可以哎(实际上是看着以前写的代码,边看边写代码T_T)。当然,中间出现了一些小问题,都是对知识的不熟练导致的。得出的一个最重要的结论就是,数据结构还是要练一练才行,光学理论,脑子里就不会有完整的流程,就会慌,脑子里空白的。

二 正文

2.1 简陋的二叉树序列化

A 过程简述

先用buildtree函数生成一个二叉树。其中#表示NULL
在这里插入图片描述
使用前序,将其序列化后,得到[1, 2, -1, 4, -1, -1, 3, -1, -1]。其中-1表示NULL

可以看出来,这就是输出前序遍历结果嘛

labuladong大佬的是输出序列,字符串形式的,我全部用整数的来弄。

B 程序代码

以下为serialize子函数

// 根据二叉树,得到一个数组序列:元素,结尾加上-1
void serialize(Bptr root, int a[])
{
    static int i = 0; // 利用static变量,元素可以逐个输入到数组中

    // deadline部分
    if (!root)
    {
        a[i++] = -1;
        return;
    }
	
	// preorder部分
    a[i++] = root->data;
    serialize(root->Lson, a);
    serialize(root->Rson, a);
}

C 完整代码

序列化完整代码

#include <iostream>
#include <stdio.h>

using namespace std;

// 树定义结点
typedef struct Bnode
{
    int data;
    struct Bnode * Lson;
    struct Bnode * Rson;
} Bnode, *Bptr;

// 函数声明
void serialize(Bptr root, int a[]); // 序列化:从二叉树得到一维的序列,本质是二叉树的遍历
Bptr buildtree();

// 全局定义
const int ZERO = -1;

// 主函数:将二叉树序列化
int main()
{
    Bptr root;
    int i;
    int a[9] = {-1};

	// 序列准备
    for (i=0; i<9; i++)
        cout << a[i] << " ";
    cout << endl;
	
	// 序列化
    root = buildtree();
    serialize(root, a);
	
	// 输出结果序列
    for (i=0; i<9; i++)
         cout << a[i] << " ";
    cout << endl;

    system("pause");
    return 0;
}

Bptr buildtree() //建立二叉树一定是NULL结尾的,输出可以把NULL换成其他的
{
    int x;
    Bptr root;
    
    cout << "Enter the node " << endl;
    cin >> x;
    if (x == ZERO) //deadline
        return NULL;

    root = new Bnode;
    root->data = x;
    root->Lson = buildtree();
    root->Rson = buildtree();

    return root;
}

// 根据二叉树,得到一个数组序列:元素,结尾加上-1
void serialize(Bptr root, int a[])
{
    static int i = 0; // 利用static变量,元素可以逐个输入到数组中

    // deadline部分
    if (!root)
    {
        a[i++] = -1;
        return;
    }
	
	// preorder部分
    a[i++] = root->data;
    serialize(root->Lson, a);
    serialize(root->Rson, a);
}

结果:
在这里插入图片描述

2.2 简陋的二叉树反序列化

A 过程简述

反序列化就是:根据已知的序列数组[1, 2, -1, 4, -1, -1, 3, -1, -1],建立一个二叉树,其中-1表示NULL

B 程序代码

// 根据数组序列,得到一个二叉树:-1表示结尾
Bptr deserialize(int a[])
{
    int x; 
    static int i = 0;
    Bptr root;

    x = a[i++]; // deadline
    if (x == ZERO)  
    {
        return NULL;
    }

    root = new Bnode; // build the tree
    root->data = x;
    root->Lson = deserialize(a);
    root->Rson = deserialize(a);

    return root;
}

C 完整代码

反序列化完整程序

#include <iostream>
#include <stdio.h>

using namespace std;

// 树定义结点
typedef struct Bnode
{
    int data;
    struct Bnode * Lson;
    struct Bnode * Rson;
} Bnode, *Bptr;

// 函数声明
Bptr deserialize(int a[]); // 反序列化:从一维的序列,得到二叉树
void preorder(Bptr root);

// 全局定义
const int ZERO = -1;

// 主函数:二叉树反序列化
int main()
{
    Bptr root;
    int i;
    int b[] = {1, 2, -1, 4, -1, -1, 3, -1, -1};

    root = deserialize( b ); //反序列化
    preorder(root);

    system("pause");
    return 0;
}

void preorder(Bptr root)
{
    if (!root) // deadline
    {
        cout << ZERO << " ";
        return;
    }

    cout << root->data << " "; // preorder
    preorder(root->Lson);
    preorder(root->Rson);
}

// 根据数组序列,得到一个二叉树:-1表示结尾
Bptr deserialize(int a[])
{
    int x; 
    static int i = 0;
    Bptr root;

    x = a[i++]; // deadline
    if (x == ZERO)  
    {
        return NULL;
    }

    root = new Bnode; // build the tree
    root->data = x;
    root->Lson = deserialize(a);
    root->Rson = deserialize(a);

    return root;
}

结果为:
在这里插入图片描述

三 问题与总结

刚开始写前言的时候,有很多总结想法的,但是写完正文,感觉没啥总结和想法了,T_T。下次问题和总结先写。

  1. 建立二叉树时,叶结尾后面跟着的都是NULL,没有别的。
  2. 数据结构,要多实践,手动去敲代码;
  3. 把数据结构全部总结一遍,还要敲对应的实现代码。
  4. Visio牛逼,可以画数据结构,数组,以前还没发现。

参考文献

[1] labuladong. 二叉树的题,就那几个框架,枯燥至极🤔. 微信. 2020. https://mp.weixin.qq.com/s/DVX2A1ha4xSecEXLxW_UsA

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值