二叉树为什么可以转换为广义表:
二叉树可以转换为广义表,主要是基于它们之间在结构上的相似性和广义表表示数据结构的灵活性。广义表转换为二叉树也是同样的原理。
代码如下:
一、创建一个结构体表示二叉树节点:
typedef struct Node{
int key; //节点的值
struct Node *lchild,*rchild; //左、右节点
}Node;
二、创建一个函数(能够初始化生成节点):
Node *getNewNode(int key){
Node *p=(Node *)malloc(sizeof(Node)); //开辟内存空间
p->key=key; //赋值
p->lchild=NULL; //初始化左节点
p->rchild=NULL; //初始化右节点
return p;
}
三、创建一个函数(能够插入新的节点):
Node *insert(Node *root,int key){
if(root==NULL)return getNewNode(key); //如果根节点为空,则创建一个新节点并返回
if(rand()%2) root->lchild=insert(root->lchild,key); //递归随机插入左节点
else root->rchild=insert(root->rchild,key); //递归随机插入右节点
return root;
}
四、创建一个函数(能够释放存储空间):
void clear(Node *root){
if(root==NULL)return; //如果根节点为空,return
if(root->lchild)clear(root->lchild); //删除左子树
if(root->rchild)clear(root->rchild); //删除右子树
free(root); //删除根节点
return;
}
五、二叉树转换为广义表:
char buff[1000]; //定义一个字符数组来存储生成的广义表
int len; //计算广义表的长度
void __serialize(Node *root){ //转换为广义表(前序遍历)
if(root==NULL)return; //如果根节点为空,return
len+=snprintf(buff+len,100,"%d",root->key); //使用snprintf(char *[],int,"类型","值")方法将根节点写入buff数组
if(root->lchild==NULL && root->rchild==NULL)return; //如果该节点左右子树皆空,return;
len+=snprintf(buff+len,100,"("); //使用snprintf()方法写入左括号
__serialize(root->lchild); //递归左子树节点
if(root->rchild){
len+=snprintf(buff+len,100,","); //若右子树存在,则写入中间的逗号
__serialize(root->rchild); //递归右子树节点
}
len+=snprintf(buff+len,100,")"); //最后写入右括号,snprintf()返回值为每次写入了多少个字符个数
return;
}
void serialize(Node *root){
memset(buff,0,sizeof(buff)); //初始化buff数组
len=0; //初始化长度
__serialize(root); //调用转换函数
return;
}
六、广义表转换为二叉树:
Node *deserialize(char *buff,int n){
Node **s=(Node **)malloc(sizeof(Node *)*10); //创建一个指针数组,并开辟空间,模拟栈
int top=-1,flag=0,scode=0; //top表示栈下标,flag表示左、右括号,scode表示转换流程状态码
Node *p=NULL,*root=NULL; //p为生成新的节点,root为根节点
for(int i=0;buff[i];i++){ //循环buff数组
switch(scode){
case 0:{ //0状态
if(buff[i]>='0'&&buff[i]<='9')scode=1; //1状态处理节点的值
else if(buff[i]=='(')scode=2; //2状态处理左括号
else if(buff[i]==',')scode=3; //3状态处理中间逗号
else scode=4; //4状态处理右括号
i-=1; //解决for循环一次后i+1操作与该switch未处理状态的冲突
break;
}
case 1:{
int key=0;
while(buff[i]<='9'&&buff[i]>='0'){
key=key*10+(buff[i]-'0'); //获取广义表中表示二叉树节点的值,字符数-'0'=数
i+=1; //循环i+1操作
}
p=getNewNode(key); //生成新的节点
if(top>=0&&flag==0)s[top]->lchild=p; //左括号,生成左节点
if(top>=0&&flag==1)s[top]->rchild=p; //右括号,生成右节点
i-=1; //解决while循环最后i+1操作后不是数字字符时与for循环i+1操作的冲突
scode=0; //初始化状态码,重新作出选择
break;
}
case 2:{
s[++top]=p; //将新节点压入栈,p不为空,因为2(3,4),2为根节点,先执行1状态操作
flag=0; //标记为左括号
scode=0; //初始化状态码,重新作出选择
break;
}
case 3:{
flag=1; //中间有逗号,说明存在右节点,标记为右括号
scode=0; //初始化状态码,重新作出选择
break;
}
case 4:{
root=s[top]; //弹出栈中元素
top-=1; //下标-1
scode=0; //初始化状态码,重新作出选择
break;
}
}
}
return root;
}
完整代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#define KEY(n) (n ? n->key : -1)
typedef struct Node{
int key;
struct Node *lchild,*rchild;
}Node;
Node *getNewNode(int key){
Node *p=(Node *)malloc(sizeof(Node));
p->key=key;
p->lchild=NULL;
p->rchild=NULL;
return p;
}
Node *insert(Node *root,int key){
if(root==NULL)return getNewNode(key);
if(rand()%2) root->lchild=insert(root->lchild,key);
else root->rchild=insert(root->rchild,key);
return root;
}
Node *getRandomBrinaryTree(int n){
Node *root=NULL;
for(int i=0;i<n;i++){
root=insert(root,rand()%1000+1);
}
return root;
}
void clear(Node *root){
if(root==NULL)return;
if(root->lchild)clear(root->lchild);
if(root->rchild)clear(root->rchild);
free(root);
return;
}
char buff[1000];
int len;
void __serialize(Node *root){
if(root==NULL)return;
len+=snprintf(buff+len,100,"%d",root->key);
if(root->lchild==NULL && root->rchild==NULL)return;
len+=snprintf(buff+len,100,"(");
__serialize(root->lchild);
if(root->rchild){
len+=snprintf(buff+len,100,",");
__serialize(root->rchild);
}
len+=snprintf(buff+len,100,")");
return;
}
void serialize(Node *root){
memset(buff,0,sizeof(buff));
len=0;
__serialize(root);
return;
}
void print(Node *root){
if(root==NULL)return;
printf("%d[%d,%d]\n",KEY(root),KEY(root->lchild),KEY(root->rchild));
return;
}
void output(Node *root){
print(root);
if(root->lchild)output(root->lchild);
if(root->rchild)output(root->rchild);
return;
}
Node *deserialize(char *buff,int n){
Node **s=(Node **)malloc(sizeof(Node *)*10);
int top=-1,flag=0,scode=0;
Node *p=NULL,*root=NULL;
for(int i=0;buff[i];i++){
switch(scode){
case 0:{
if(buff[i]>='0'&&buff[i]<='9')scode=1;
else if(buff[i]=='(')scode=2;
else if(buff[i]==',')scode=3;
else scode=4;
i-=1;
break;
}
case 1:{
int key=0;
while(buff[i]<='9'&&buff[i]>='0'){
key=key*10+(buff[i]-'0');
i+=1;
}
p=getNewNode(key);
if(top>=0&&flag==0)s[top]->lchild=p;
if(top>=0&&flag==1)s[top]->rchild=p;
i-=1;
scode=0;
break;
}
case 2:{
s[++top]=p;
flag=0;
scode=0;
break;
}
case 3:{
flag=1;
scode=0;
break;
}
case 4:{
root=s[top];
top-=1;
scode=0;
break;
}
}
}
return root;
}
int main(){
srand(time(0));
Node *root=NULL;
root=getRandomBrinaryTree(10);
output(root);
serialize(root);
printf("\n");
printf("BUFF:%s\n",buff);
Node *get_root=deserialize(buff,len);
output(get_root);
clear(root);
return 0;
}