广义表+ADT+C语言实现

广义表

线性表的推广

(1)表的元素可以是子表,子表的元素还可以是子表

(2)列表为其他列表所享有

(3)列表可以是一个可以递归的表,即列表可以是其本身的子表

广义表一般记作:

LS = (\alpha1,\alpha2,\alpha3...\alpha n)

\alpha i 可以是单个元素,也可以是广义表,分别为广义表LS的原子子表

习惯上,用大写字母表示广义表的名称,用小写字母表示原子。

当广义表LS非空时,称第一个元素 \alpha1 为LS的表头(Head),称其余元素组成的表(\alpha2,\alpha3,...,\alpha n)是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(\alpha i)} 

// 广义表.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 

猜你喜欢

转载自blog.csdn.net/qq_40479037/article/details/84993984