#广义表简介
广义表是线性表的推广,也是一种基础的数据结构。广义表类似于数组,不同的是,广义表里面可以存储广义表,即储存单个元素或者多个元素组成的广义表。其中,单个元素称为原子,广义表中的广义表称为子表,甚至子表的子表还可以是广义表。广义表内部类似于一种递归结构。
广义表第一个元素称为表头,表头后面的称为表尾。其中,表头可以使原子或者广义表,表尾一定是广义表,哪怕是空表。
#广义表存储链表的两种结点方式
虽然广义表类似于数组,但是由于广义表储存的元素大小可能不一样(原子和子表),所以采用链表的方式进行储存,并且结点结构包括对原子的储存和子表的储存,还涉及到两种不同的结点结构。
##头尾链表存储表示
第一种就是图上所示的表示,有一个共同的tag标志用于区分原子和子表。子表有一个头指针和尾指针;原子有一个数据域。接下来就是代码实现:
//广义表的存储实现
//1.0 标志位
typedef enum MyEnum
{
ATOM1,
LIST1
}Tag;
//2.0 结点表示(头尾形式)
typedef struct GLNode
{
Tag tag;
union
{
char data;
struct
{
struct GLNode *hp,*tp;
}ptr;
};
}*GList,GNode;
接下来是使用这种储存方式进行广义表的创建和储存,两种存储的元素都是{a,{c,s,l}}
//1.0 广义表的创建 头尾链表法
GList creatGlist(GList head) {
//广义表C
head = (GList)malloc(sizeof(GList)); //表结点类型指针 C是一个表头指针
head->tag = LIST1; //初始化为广义表
//表头原子‘a’
head->ptr.hp = (GList)malloc(sizeof(GList));
head->ptr.hp->tag = ATOM1;
head->ptr.hp->data = 'a'; //表头原子
//表尾子表(c,s,l),是一个整体
head->ptr.tp = (GList)malloc(sizeof(GList)); //表尾指针指向表尾,表尾一定是一个列表(可能是空列表),所以表尾指针相当于一个表头指针
head->ptr.tp->tag = LIST1;
head->ptr.tp->ptr.hp = (GList)malloc(sizeof(GList));
head->ptr.tp->ptr.tp = NULL;
//开始存放下一个元素(c,s,l),其中c为表头,(s,l)为尾
head->ptr.tp->ptr.hp->tag = LIST1;
//C->ptr.tp->ptr.hp->ptr.hp = (GList)malloc(sizeof(GList));
head->ptr.tp->ptr.hp->tag = ATOM1;
head->ptr.tp->ptr.hp->data = 'c';
head->ptr.tp->ptr.hp->ptr.tp = (GList)malloc(sizeof(GList));
//存放's,l'
head->ptr.tp->ptr.hp->ptr.tp->tag = LIST1;
head->ptr.tp->ptr.hp->ptr.tp->ptr.hp = (GList)malloc(sizeof(GList));
head->ptr.tp->ptr.hp->ptr.tp->ptr.hp->tag = ATOM1;
head->ptr.tp->ptr.hp->ptr.tp->ptr.hp->data = 's';
head->ptr.tp->ptr.hp->ptr.tp->ptr.tp = (GList)malloc(sizeof(GList));
//存放'l'
head->ptr.tp->ptr.hp->ptr.tp->ptr.tp->tag = LIST1;
head->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp = (GList)malloc(sizeof(GList));
head->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp->tag = ATOM1;
head->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp->data = 'l';
head->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.tp = NULL;
return head;
}
接下来计算广义表的长度(注意广义表的长度和深度的区别)
//获取广义表的长度
int getLength(GList head)
{
int number = 0;
GList P = head;
while (P)
{
number++;
P = P->ptr.tp;
}
return number;
}
运行结果:
在运行时有时候出现这种情况,不知道哪位大佬能解答一下:
##第二种结点方式
这里把tp提取出来,相当于一个next指针。与第一种不同的是,这里的原子结点有了指向下一个结点的指针,而第一中原子与原子之间是相互独立的,通过表结点相互连接(这两种图在数据结构的相关书籍上应该都有,要画的话有点麻烦,原谅我偷懒_----)
代码实现:
//1.0.1 广义表的表示以及创建第二种表达方式
typedef enum
{
ATOM,
LIST
}Tag2;
typedef struct GLnode2
{
Tag2 tag2;
union
{
char data;
struct
{
struct GLnode2 *hp;
}ptr;
};
struct GLnode2 *tp;
}*GList2,GNode2;
接下来使用第二种结点结构进行广义表创建以及元素的储存:
GList2 creatGList2(GList2 head)
{
//整个广义表
head = (GList2)malloc(sizeof(GList2));
head->tag2 = LIST;
//表头原子'a'
head->ptr.hp = (GList2)malloc(sizeof(GList2));
head->ptr.hp->tag2 = ATOM;
head->ptr.hp->data = 'a';
//整体的c,s,l
head->tp = (GList2)malloc(sizeof(GList2));
head->tp->ptr.hp = (GList2)malloc(sizeof(GList2));
head->tp->tag2 = LIST;
head->tp->tp = NULL;
//下一个元素c
head->tp->ptr.hp->tag2 = ATOM;
head->tp->ptr.hp->data = 'c';
head->tp->ptr.hp->tp = (GList2)malloc(sizeof(GList2));
//s,l;
head->tp->ptr.hp->tp = (GList2)malloc(sizeof(GList2));
head->tp->ptr.hp->tp->tag2 = ATOM;
head->tp->ptr.hp->tp->data = 's';
head->tp->ptr.hp->tp->tp = (GList2)malloc(sizeof(GList2));
//l
head->tp->ptr.hp->tp->tp->tag2 = ATOM;
head->tp->ptr.hp->tp->tp->data = 'l';
head->tp->ptr.hp->tp->tp = NULL;
return head;
}
很明显,第二种方式相对于第一种显得精简很多。
长度:
//获取广义表的长度
int getLength2(GList2 get)
{
int number = 0;
while (get)
{
number++;
get = get->tp;
}
return number;
}
运行结果:
上面是我学习数据结构广义表的时候的随笔,肯定有很多不知道的错误。希望大家指出,在后续我也将不断完善。上面也有从网上借鉴,如果有侵权或者不想在本文中出现的请联系我,谢谢大家!