一 前言
本宝宝好好的上午,本来打算把操作系统的视频刷两章,然后看到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。下次问题和总结先写。
- 建立二叉树时,叶结尾后面跟着的都是
NULL
,没有别的。 - 数据结构,要多实践,手动去敲代码;
- 把数据结构全部总结一遍,还要敲对应的实现代码。
- Visio牛逼,可以画数据结构,数组,以前还没发现。
参考文献
[1] labuladong. 二叉树的题,就那几个框架,枯燥至极🤔. 微信. 2020. https://mp.weixin.qq.com/s/DVX2A1ha4xSecEXLxW_UsA