广义表的头尾链表存储表示(第五章 P115 算法5.5,5.6,5.8)

 

 

 /* 广义表的头尾链表存储表示 */
 typedef enum{ATOM,LIST}ElemTag; /* ATOM==0:原子,LIST==1:子表 */
 typedef struct GLNode
 {
   ElemTag tag; /* 公共部分,用于区分原子结点和表结点 */
   union /* 原子结点和表结点的联合部分 */
   {
     AtomType atom; /* atom是原子结点的值域,AtomType由用户定义 */
     struct
     {
       struct GLNode *hp,*tp;
     }ptr; /* ptr是表结点的指针域,prt.hp和ptr.tp分别指向表头和表尾 */
   }a;
 }*GList,GLNode; /* 广义表类型 */

 

下图是根据上方程序定义的广义表(a,(b,c,d))的存储结构。它的长度为 2,第 1 个元素为原子 a,第 2 个元素为子表(b,c,d)

 

完整代码:

下面代码中广义表的书写形式串为SString类型,广义表的书写形式串为HString类型的请转看:https://blog.csdn.net/qq_42185999/article/details/105670495

 

typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */

#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */
#include<limits.h> //常量INT_MAX和INT_MIN分别表示最大、最小整数

/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2 

typedef char AtomType; /* 定义原子类型为字符型 */


/* ---------------------------------  广义表的头尾链表存储表示    --------------------------------*/

typedef enum { ATOM, LIST }ElemTag; /* ATOM==0:原子,LIST==1:子表 */
typedef struct GLNode
{
	ElemTag tag; /* 公共部分,用于区分原子结点和表结点 */
	union /* 原子结点和表结点的联合部分 */
	{
		AtomType atom; /* atom是原子结点的值域,AtomType由用户定义 */
		struct
		{
			struct GLNode *hp, *tp;
		}ptr; /* ptr是表结点的指针域,prt.hp和ptr.tp分别指向表头和表尾 */
	}a;
}*GList, GLNode; /* 广义表类型 */

/* ---------------------------------------------------------------------------------------------*/




/* ---------------------------  广义表的头尾链表存储的基本操作(11个)  --------------------------*/

Status InitGList(GList *L)
{ /* 创建空的广义表L */
	*L = NULL;
	return OK;
}

void DestroyGList(GList *L) /* 广义表的头尾链表存储的销毁操作 */
{ /* 销毁广义表L */
	GList q1, q2;
	if (*L)
	{
		if ((*L)->tag == ATOM)
		{
			free(*L); /* 删除原子结点 */
			*L = NULL;
		}
		else /* 删除表结点 */
		{
			q1 = (*L)->a.ptr.hp;
			q2 = (*L)->a.ptr.tp;
			free(*L);
			*L = NULL;
			DestroyGList(&q1);
			DestroyGList(&q2);
		}
	}
}

Status CopyGList(GList *T, GList L)
{ /* 采用头尾链表存储结构,由广义表L复制得到广义表T。算法5.6 */
	if (!L) /* 复制空表 */
		*T = NULL;
	else
	{
		*T = (GList)malloc(sizeof(GLNode)); /* 建表结点 */
		if (!*T)
			exit(OVERFLOW);
		(*T)->tag = L->tag;
		if (L->tag == ATOM)
			(*T)->a.atom = L->a.atom; /* 复制单原子 */
		else
		{
			CopyGList(&((*T)->a.ptr.hp), L->a.ptr.hp);
			/* 复制广义表L->ptr.hp的一个副本T->ptr.hp */
			CopyGList(&((*T)->a.ptr.tp), L->a.ptr.tp);
			/* 复制广义表L->ptr.tp的一个副本T->ptr.tp */
		}
	}
	return OK;
}

int GListLength(GList L)
{ /* 返回广义表的长度,即元素个数 */
	int len = 0;
	if (!L)
		return 0;
	if (L->tag == ATOM)
		return 1;
	while (L)
	{
		L = L->a.ptr.tp;
		len++;
	}
	return len;
}

int GListDepth(GList L)
{ /* 采用头尾链表存储结构,求广义表L的深度。算法5.5 */
	int max, dep;
	GList pp;
	if (!L)
		return 1; /* 空表深度为1 */
	if (L->tag == ATOM)
		return 0; /* 原子深度为0 */
	for (max = 0, pp = L; pp; pp = pp->a.ptr.tp)
	{
		dep = GListDepth(pp->a.ptr.hp); /* 求以pp->a.ptr.hp为头指针的子表深度 */
		if (dep > max)
			max = dep;
	}
	return max + 1; /* 非空表的深度是各元素的深度的最大值加1 */
}

Status GListEmpty(GList L)
{ /* 判定广义表是否为空 */
	if (!L)
		return TRUE;
	else
		return FALSE;
}

GList GetHead(GList L)
{ /* 取广义表L的头 */
	GList h, p;
	if (!L)
	{
		printf("空表无表头!\n");
		exit(0);
	}
	p = L->a.ptr.tp;
	L->a.ptr.tp = NULL;
	CopyGList(&h, L);
	L->a.ptr.tp = p;
	return h;
}

GList GetTail(GList L)
{ /* 取广义表L的尾 */
	GList t;
	if (!L)
	{
		printf("空表无表尾!\n");
		exit(0);
	}
	CopyGList(&t, L->a.ptr.tp);
	return t;
}

Status InsertFirst_GL(GList *L, GList e)
{ /* 初始条件: 广义表存在 */
  /* 操作结果: 插入元素e作为广义表L的第一元素(表头,也可能是子表) */
	GList p = (GList)malloc(sizeof(GLNode));
	if (!p)
		exit(OVERFLOW);
	p->tag = LIST;
	p->a.ptr.hp = e;
	p->a.ptr.tp = *L;
	*L = p;
	return OK;
}

Status DeleteFirst_GL(GList *L, GList *e)
{ /* 初始条件: 广义表L存在 */
  /* 操作结果: 删除广义表L的第一元素,并用e返回其值 */
	GList p;
	*e = (*L)->a.ptr.hp;
	p = *L;
	*L = (*L)->a.ptr.tp;
	free(p);
	return OK;
}

void Traverse_GL(GList L, void(*v)(AtomType))
{ /* 利用递归算法遍历广义表L */
	if (L) /* L不空 */
		if (L->tag == ATOM) /* L为单原子 */
			v(L->a.atom);
		else /* L为广义表 */
		{
			Traverse_GL(L->a.ptr.hp, v);
			Traverse_GL(L->a.ptr.tp, v);
		}
}


/* --------------------------------------------------------------------------------------------------*/



 /* 广义表的书写形式串为SString类型 */





/* ----------------------------------  串的定长顺序存储表示  -----------------------------------*/

#define MAXSTRLEN 40 /* 用户可在255以内定义最大串长(1个字节) */
typedef char SString[MAXSTRLEN + 1]; /* 0号单元存放串的长度 */

/* ---------------------------------------------------------------------------------------------*/


/* -------------------------  需要用到的串采用定长顺序存储结构的基本操作  ------------------------*/


Status StrAssign(SString T, char *chars)
{ /* 生成一个其值等于chars的串T */
	int i;
	if (strlen(chars) > MAXSTRLEN)
		return ERROR;
	else
	{
		T[0] = strlen(chars);
		for (i = 1; i <= T[0]; i++)
			T[i] = *(chars + i - 1);
		return OK;
	}
}

Status StrCopy(SString T, SString S)
{ /* 由串S复制得串T */
	int i;
	for (i = 0; i <= S[0]; i++)
		T[i] = S[i];
	return OK;
}

Status StrEmpty(SString S)
{ /* 若S为空串,则返回TRUE,否则返回FALSE */
	if (S[0] == 0)
		return TRUE;
	else
		return FALSE;
}

int StrCompare(SString S, SString T)
{ /* 初始条件: 串S和T存在 */
  /* 操作结果: 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 */
	int i;
	for (i = 1; i <= S[0] && i <= T[0]; ++i)
		if (S[i] != T[i])
			return S[i] - T[i];
	return S[0] - T[0];
}

int StrLength(SString S)
{ /* 返回串的元素个数 */
	return S[0];
}

Status ClearString(SString S)
{ /* 初始条件:串S存在。操作结果:将S清为空串 */
	S[0] = 0;/* 令串长为零 */
	return OK;
}

Status SubString(SString Sub, SString S, int pos, int len)
{ /* 用Sub返回串S的第pos个字符起长度为len的子串。算法4.3 */
	int i;
	if (pos<1 || pos>S[0] || len<0 || len>S[0] - pos + 1)
		return ERROR;
	for (i = 1; i <= len; i++)
		Sub[i] = S[pos + i - 1];
	Sub[0] = len;
	return OK;
}


/* -----------------------------------------------------------------------------------------------*/




void sever(SString str, SString hstr) /* 算法5.8  SString是数组,不需引用类型 */
{ /* 将非空串str分割成两部分:hsub为第一个','之前的子串,str为之后的子串 */
	int n, k, i; /* k记尚未配对的左括号个数 */
	SString ch, c1, c2, c3;
	n = StrLength(str);
	StrAssign(c1, ",");
	StrAssign(c2, "(");
	StrAssign(c3, ")");
	SubString(ch, str, 1, 1);
	for (i = 1, k = 0; i <= n && StrCompare(ch, c1) || k != 0; ++i)
	{ /* 搜索最外层的第一个逗号 */
		SubString(ch, str, i, 1);
		if (!StrCompare(ch, c2))
			++k;
		else if (!StrCompare(ch, c3))
			--k;
	}
	if (i <= n)
	{
		SubString(hstr, str, 1, i - 2);
		SubString(str, str, i, n - i + 1);
	}
	else
	{
		StrCopy(hstr, str);
		ClearString(str);
	}
}

Status CreateGList(GList *L, SString S) /* 算法5.7 */
{ /* 采用头尾链表存储结构,由广义表的书写形式串S创建广义表L。设emp="()" */
	SString sub, hsub, emp;
	GList p, q;
	StrAssign(emp, "()");
	if (!StrCompare(S, emp))
		*L = NULL; /* 创建空表 */
	else
	{
		*L = (GList)malloc(sizeof(GLNode));
		if (!*L) /* 建表结点 */
			exit(OVERFLOW);
		if (StrLength(S) == 1) /* S为单原子 */
		{
			(*L)->tag = ATOM;
			(*L)->a.atom = S[1]; /* 创建单原子广义表 */
		}
		else
		{
			(*L)->tag = LIST;
			p = *L;
			SubString(sub, S, 2, StrLength(S) - 2); /* 脱外层括号 */
			do
			{ /* 重复建n个子表 */
				sever(sub, hsub); /* 从sub中分离出表头串hsub */
				CreateGList(&p->a.ptr.hp, hsub);
				q = p;
				if (!StrEmpty(sub)) /* 表尾不空 */
				{
					p = (GLNode *)malloc(sizeof(GLNode));
					if (!p)
						exit(OVERFLOW);
					p->tag = LIST;
					q->a.ptr.tp = p;
				}
			} while (!StrEmpty(sub));
			q->a.ptr.tp = NULL;
		}
	}
	return OK;
}




 /* 主程序 */


void visit(AtomType e)
{
	printf("%c ", e);
}

void main()
{
	char p[80];
	SString t;
	GList l, m;
	InitGList(&l);
	InitGList(&m);
	printf("空广义表l的深度=%d l是否空?%d(1:是 0:否)\n", GListDepth(l), GListEmpty(l));
	printf("请输入广义表l(书写形式:空表:(),单原子:a,其它:(a,(b),b)):\n");
	gets(p);
	StrAssign(t, p);
	CreateGList(&l, t);
	printf("广义表l的长度=%d\n", GListLength(l));
	printf("广义表l的深度=%d l是否空?%d(1:是 0:否)\n", GListDepth(l), GListEmpty(l));
	printf("遍历广义表l:\n");
	Traverse_GL(l, visit);
	printf("\n复制广义表m=l\n");
	CopyGList(&m, l);
	printf("广义表m的长度=%d\n", GListLength(m));
	printf("广义表m的深度=%d\n", GListDepth(m));
	printf("遍历广义表m:\n");
	Traverse_GL(m, visit);
	DestroyGList(&m);
	m = GetHead(l);
	printf("\nm是l的表头,遍历广义表m:\n");
	Traverse_GL(m, visit);
	DestroyGList(&m);
	m = GetTail(l);
	printf("\nm是l的表尾,遍历广义表m:\n");
	Traverse_GL(m, visit);
	InsertFirst_GL(&m, l);
	printf("\n插入l为m的表头,遍历广义表m:\n");
	Traverse_GL(m, visit);
	printf("\n删除m的表头,遍历广义表m:\n");
	DestroyGList(&l);
	DeleteFirst_GL(&m, &l);
	Traverse_GL(m, visit);
	printf("\n");
	DestroyGList(&m);
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值