广义表
线性表的推广
(1)表的元素可以是子表,子表的元素还可以是子表
(2)列表为其他列表所享有
(3)列表可以是一个可以递归的表,即列表可以是其本身的子表
广义表一般记作:
可以是单个元素,也可以是广义表,分别为广义表LS的原子和子表
习惯上,用大写字母表示广义表的名称,用小写字母表示原子。
当广义表LS非空时,称第一个元素 为LS的表头(Head),称其余元素组成的表()是LS的表尾(Tail)
任何一个非空列表其表头可能是原子,也可能是列表,而其表尾必定为列表
(1)A = ()
(2)B = (e)
(3)C = (a,(b,c,d))
(4)D = (A,B,C)
GetHead(B) = e GetTail(B) = ()
GetHead(D) = A GetTail(D) = (B,C)
GetHead((B,C)) = B GetTail((B,C)) = (C)
()(空表)长度为0,(())(非空表)长度为1
广义表的存储结构
表结点
tag = 1 | hp | tp |
原子结点
tag = 0 | atom |
ADT
ADT GList{
数据对象:D={ei|i=1,2,...,n;n>=0;ei∈AtomSet或ei∈GList,
AtomSet为某个数据对象}
数据关系:R1={<ei-1,ei>|ei-1,ei∈D,2<=i<=n}
基本操作:
InitGList(&L);
操作结果:创建空的广义表.
CreateGList(&L,S);
初始条件:S是广义表的书写形式串。
操作结果:有S创建广义表L。
DestoryGList(&L);
初始条件:广义表L存在
操作结果:销毁广义表L。
CopyGList(&T,L);
初始条件:广义表L存在
操作结果:由广义表L复制得到广义表T。
GListLength(L);
初始条件:广义表L存在
操作结果:求广义表的长度,即元素个数
GListDepth(L);
初始条件:广义表L的深度
操作结果:求广义表的深度
GListEmpty(L);
初始条件:广义表存在
操作结果:判定广义表L是否为空
GetHead(L);
初始条件:广义表L存在
操作结果:取广义表L的头
GetTail(L);
初始条件:广义表L存在
操作结果:取广义表的尾
InsertFirst_GL(&L,e);
初始条件:广义表L存在
操作结果:插入元素e作为广义表的第一元素。
DeleteFirst_GL(&L,&e);
初始条件:广义表L存在
操作结果:删除广义表L的第一个元素,并用e返回其值
Traverse_GL(L,visit());
初始条件:广义表L存在
操作结果:遍历广义表L,用函数visit处理每个元素
}ADT GList;
建立广义表
基本项:
当S为空表串时,置空广义表
当S为单字符串时,建原子结点子表
归纳项:
sub为脱去最外层括弧的子串,'s1,s2,...,sn',为非空子串。对每一个Si建立一个表结点,并令其hp域的指针为由si建立的子表的头指针,除最后建立的表结点的尾指针为NULL之外,其余表结点的为指针均指向在它之后建立的表结点。
复制广义表
基本项:
InitGList(NEXLS){置空表},当LS为空表时
归纳项:
COPY(GetHead(LS)->GetHead(NEWLS)){复制表头}
COPY(GetTail(LS)->GetTail(NEWLS)){复制表尾}
求广义表的深度
基本项:
DEPTH(LS)=1 当LS为空表时
DEPTH(LS)=0 当LS为原子时
归纳项:
DEPTH(LS)=1+Max{DEPTH(
)}
// 广义表.cpp : 定义控制台应用程序的入口点。
//以字符串形式
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# define Status int
# define AtomType char
# define OK 1
# define ERROR 0
# define OVERFLOW -1
# define MaxLength 60
# include<iostream>
using namespace std;
typedef struct
{
AtomType str[MaxLength];
Status length;
}SString;//自定义字符串
typedef enum {ATOM,LIST}ElemTag;//ATOM=0表示原子,List=1表示子表
typedef struct GLNode
{
ElemTag tag;//标志tag用于区分元素是原子还是子表
union
{
AtomType atom;//原子结点的值域,用户自己定义的类型
struct {
struct GLNode *hp, *tp;//hp指向表头,tp指向表尾
}ptr;
};
}*GList,GLNode;
//判断是否为空字符串
Status StrEmpty(SString S)
{
if (S.length == 0)
return OK;
else
return ERROR;
}
//求串长度
Status StrLength(SString S)
{
return S.length;
}
//串比较
Status StrCompare(SString S, SString T)
{
int i;
for (i = 0; i < S.length && i < T.length; ++i)
{
if (S.str[i] != T.str[i])
return S.str[i] - T.str[i];//返回第一个比较不同字符的大小
}
return S.length - T.length;//比较结束,返回两个串差值
}
//清空串
void StrClear(SString *S)
{
S->length = 0;
}
//串的赋值操作
void StrCopy(SString *T, SString S)
{
int i;
for (i = 0; i < S.length; ++i)
{
T->str[i] = S.str[i];
}
T->length = S.length;
}
//串赋值
void StrAssign(SString *S, char str[])
{
int i;
for (i = 0; str[i] != '\0'; ++i)
S->str[i] = str[i];
S->length = i;
}
//截取从pos开始的长度为len的子串
Status SubString(SString *Sub,SString S,int pos,int len)
{
int i;
if (pos < 0 || len < 0 || pos + len - 1 > S.length)
{
printf("参数不合法!\n");
return ERROR;
}
else
{
for (i = 0; i < len; ++i)
Sub->str[i] = S.str[i + pos - 1];
Sub->length = len;
return OK;
}
}
//将串Str分离成两个部分,HeadStr为第一个逗号之前的子串,Str为逗号后的子串
void DistributeString(SString *Str,SString *HeadStr)
{
int i, len, k;
SString ch, ch1, ch2, ch3;
len = StrLength(*Str);
StrAssign(&ch1, ",");
StrAssign(&ch2, "(");
StrAssign(&ch3, ")");
SubString(&ch, *Str, 1, 1);//ch保存Str的第一个字符
for (i = 0, k = 0; i <= len && StrCompare(ch, ch1) || k != 0; ++i)
{//搜索str的最外层的第一个括号
SubString(&ch, *Str, i, 1);
if (!StrCompare(ch, ch2))
k++;
else if (!StrCompare(ch, ch3))
k--;
}
if (i <= len)
{
SubString(HeadStr, *Str, 1, i - 2);
SubString(Str, *Str, i, len - i + 1);
}
else//只包含一个子串
{
StrCopy(HeadStr, *Str);
StrClear(Str);
}
}
//创建广义表
void CreateList(GList *L,SString S)
{
SString Sub, HeadSub, Empty;
GList p, q;
StrAssign(&Empty, "()");
if (!StrCompare(S, Empty))
*L = NULL;//如果输入是空串,则创建一个空的广义表
else
{
if (!(*L = (GList)malloc(sizeof(GLNode))))
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
if (StrLength(S) == 1)
{//原子类型广义表
(*L)->atom = S.str[0];
(*L)->tag = ATOM;
}
else
{
(*L)->tag = LIST;
p = *L;
SubString(&Sub, S, 2, StrLength(S) - 2);//去除外层括号
do {
DistributeString(&Sub, &HeadSub);//将Sub分离出表头和表尾
CreateList(&(p->ptr.hp), HeadSub);
q = p;
if (!StrEmpty(Sub))
{
if (!(p = (GLNode *)malloc(sizeof(GLNode)))) {
printf("内存分配失败!\n");
exit(OVERFLOW);
}
p->tag = LIST;
q->ptr.tp = p;
}
} while (!StrEmpty(Sub));
q->ptr.tp = NULL;
}//else else
}//else
}
//输出广义表的串表示形式
void PrintList(GList L)
{
if (!L)
{
printf("()");
}
else
{
if (L->tag == ATOM)
{
printf("%c",L->atom);
}
else
{
printf("(");
GLNode *p = L;
while (p)
{
PrintList(p->ptr.hp);
p = p->ptr.tp;
if (p)
printf(",");
}//while
printf(")");
}//else else
}//else
}
//获取广义表的表头节点
Status GetHead(GList L)
{
if (L == NULL)
{
printf("广义表为空!\n");
return ERROR;
}
GLNode *Head = L->ptr.hp;
if (Head->tag == ATOM)
{
printf("表头:%c\n",Head->atom);
}
else
{
printf("表头:");
PrintList(Head);
printf("\n");
}
return OK;
}
//获取表尾节点
Status GetTail(GList L)
{
if (L == NULL)
{
printf("空表!\n");
return ERROR;
}
GLNode *tail = L->ptr.tp;
printf("表尾:");
PrintList(tail);
printf("\n");
return OK;
}
//求广义表长度
Status GListLength(GList L)
{
int length = 0;
GLNode *p = L;
if (p == NULL)
{
printf("空表\n");
return ERROR;
}
else
{
length = GListLength(p->ptr.tp);
}
return length + 1;
}
//求广义表的深度
Status GListDepth(GList L)
{
int max,depth;
GLNode *p;
if (!L)
return 1;
if (L->tag == ATOM)
return 0;
for (max = 0, p = L; p; p = p->ptr.tp)
{
depth = GListDepth(p->ptr.hp);
if (max < depth)
max = depth;
}
return max + 1;
}
//赋值广义表
Status CopyGList(GList *T, GList L)
{
if (!L)
*T = NULL;
else
{
*T = (GList)malloc(sizeof(GLNode));
if (*T == NULL)
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
(*T)->tag = L->tag;
if (L->tag == ATOM)
(*T)->atom = L->atom;
else
{
CopyGList(&((*T)->ptr.hp), L->ptr.hp);
CopyGList(&((*T)->ptr.tp), L->ptr.tp);
}
}
return OK;
}
//求广义表原子节点的数目
int CountAtom(GList L)
{
int n1, n2;
if (L == NULL)
return ERROR;
if (L->tag == ATOM)
return 1;
n1 = CountAtom(L->ptr.hp);
n2 = CountAtom(L->ptr.tp);
return n1 + n2;
}
int main()
{
GList L, T;
SString S;
char str[60];
printf("请输入广义表:\n");
cin >> str;
StrAssign(&S,str);
CreateList(&L, S);
printf("输出广义表中的元素是:");
PrintList(L);
printf("\n");
GetHead(L);
GetTail(L);
printf("表的长度为:%d\n",GListLength(L));
printf("表的深度为:%d\n", GListDepth(L));
CopyGList(&T, L);
printf("输出广义表中的元素是:");
PrintList(T);
printf("输出广义表中原子节点个数:%d\n",CountAtom(L));
return 0;
}
参考链接:https ://blog.csdn.net/qq_28598203/article/details/51212082