广义表的扩展线性链表存储(第五章)

 

 /* 广义表的扩展线性链表存储表示 */
 typedef enum{ATOM,LIST}ElemTag; /* ATOM==0:原子,LIST==1:子表 */
 typedef struct GLNode
 {
   ElemTag tag; /* 公共部分,用于区分原子结点和表结点 */
   union /* 原子结点和表结点的联合部分 */
   {
     AtomType atom; /* 原子结点的值域 */
     struct GLNode *hp; /* 表结点的表头指针 */
   }a;
   struct GLNode *tp; /* 相当于线性链表的next,指向下一个元素结点 */
 }*GList,GLNode; /* 广义表类型GList是一种扩展的线性链表 */

下图是根据上方程序定义的广义表(a,(b,c,d))的扩展线性链表存储结构。在这种结构中,广义表的头指针所指结点的 tag 域值总是 1(),其 tp 域总是 NULL。这样看来,广义表的头指针所指结点相当于表的头结点。和广义表的线性链表存储 相比,下图这种结构更简洁些。

 

 

完整代码:

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; /* 原子结点的值域 */
		struct GLNode *hp; /* 表结点的表头指针 */
	}a;
	struct GLNode *tp; /* 相当于线性链表的next,指向下一个元素结点 */
}*GList, GLNode; /* 广义表类型GList是一种扩展的线性链表 */

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




/* --------------------------- 广义表的扩展线性链表存储的基本操作(13个)  --------------------------*/



/* -----------------------    串的堆分配存储    ------------------------------*/

typedef struct
{
	char *ch; /* 若是非空串,则按串长分配存储区,否则ch为NULL */
	int length; /* 串长度 */
}HString;

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


/* ---------------------  需要用到的串采用堆分配存储结构的基本操作  ------------------------*/


Status StrAssign(HString *T, char *chars)
{ /* 生成一个其值等于串常量chars的串T */
	int i, j;
	if ((*T).ch)
		free((*T).ch); /* 释放T原有空间 */
	i = strlen(chars); /* 求chars的长度i */
	if (!i)
	{ /* chars的长度为0 */
		(*T).ch = NULL;
		(*T).length = 0;
	}
	else
	{ /* chars的长度不为0 */
		(*T).ch = (char*)malloc(i * sizeof(char)); /* 分配串空间 */
		if (!(*T).ch) /* 分配串空间失败 */
			exit(OVERFLOW);
		for (j = 0; j < i; j++) /* 拷贝串 */
			(*T).ch[j] = chars[j];
		(*T).length = i;
	}
	return OK;
}

Status StrCopy(HString *T, HString S)
{ /* 初始条件:串S存在。操作结果: 由串S复制得串T */
	int i;
	if ((*T).ch)
		free((*T).ch); /* 释放T原有空间 */
	(*T).ch = (char*)malloc(S.length * sizeof(char)); /* 分配串空间 */
	if (!(*T).ch) /* 分配串空间失败 */
		exit(OVERFLOW);
	for (i = 0; i < S.length; i++) /* 拷贝串 */
		(*T).ch[i] = S.ch[i];
	(*T).length = S.length;
	return OK;
}

Status StrEmpty(HString S)
{ /* 初始条件: 串S存在。操作结果: 若S为空串,则返回TRUE,否则返回FALSE */
	if (S.length == 0 && S.ch == NULL)
		return TRUE;
	else
		return FALSE;
}

int StrCompare(HString S, HString T)
{ /* 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 */
	int i;
	for (i = 0; i < S.length&&i < T.length; ++i)
		if (S.ch[i] != T.ch[i])
			return S.ch[i] - T.ch[i];
	return S.length - T.length;
}

int StrLength(HString S)
{ /* 返回S的元素个数,称为串的长度 */
	return S.length;
}

Status ClearString(HString *S)
{ /* 将S清为空串 */
	if ((*S).ch)
	{
		free((*S).ch);
		(*S).ch = NULL;
	}
	(*S).length = 0;
	return OK;
}

Status SubString(HString *Sub, HString S, int pos, int len)
{ /* 用Sub返回串S的第pos个字符起长度为len的子串。 */
  /* 其中,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1 */
	int i;
	if (pos<1 || pos>S.length || len<0 || len>S.length - pos + 1)
		return ERROR;
	if ((*Sub).ch)
		free((*Sub).ch); /* 释放旧空间 */
	if (!len) /* 空子串 */
	{
		(*Sub).ch = NULL;
		(*Sub).length = 0;
	}
	else
	{ /* 完整子串 */
		(*Sub).ch = (char*)malloc(len * sizeof(char));
		if (!(*Sub).ch)
			exit(OVERFLOW);
		for (i = 0; i <= len - 1; i++)
			(*Sub).ch[i] = S.ch[pos - 1 + i];
		(*Sub).length = len;
	}
	return OK;
}

void InitString(HString *T)
{ /* 初始化(产生空串)字符串T。另加 */
	(*T).length = 0;
	(*T).ch = NULL;
}


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




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

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

Status sever(HString *str, HString *hstr) 
{ /* 将非空串str分割成两部分:hstr为第一个','之前的子串,str为之后的子串 */
	int n, i = 1, k = 0; /* k记尚未配对的左括号个数 */
	HString ch, c1, c2, c3;
	InitString(&ch); /* 初始化HString类型的变量 */
	InitString(&c1);
	InitString(&c2);
	InitString(&c3);
	StrAssign(&c1, ",");
	StrAssign(&c2, "(");
	StrAssign(&c3, ")");
	n = StrLength(*str);
	do
	{
		SubString(&ch, *str, i, 1);
		if (!StrCompare(ch, c2))
			++k;
		else if (!StrCompare(ch, c3))
			--k;
		++i;
	} while (i <= n && StrCompare(ch, c1) || k != 0);
	if (i <= n)
	{
		StrCopy(&ch, *str);
		SubString(hstr, ch, 1, i - 2);
		SubString(str, ch, i, n - i + 1);
	}
	else
	{
		StrCopy(hstr, *str);
		ClearString(str);
	}
	return OK;
}

Status CreateGList(GList *L, HString S)
{ /* 初始条件: S是广义表的书写形式串。操作结果: 由S创建广义表L */
	HString emp, sub, hsub;
	GList p;
	InitString(&emp);
	InitString(&sub);
	InitString(&hsub);
	StrAssign(&emp, "()"); /* 设emp="()" */
	*L = (GList)malloc(sizeof(GLNode));
	if (!*L) /* 建表结点不成功 */
		exit(OVERFLOW);
	if (!StrCompare(S, emp)) /* 创建空表 */
	{
		(*L)->tag = LIST;
		(*L)->a.hp = NULL;
		(*L)->tp = NULL;
	}
	else if (StrLength(S) == 1) /* 创建单原子广义表 */
	{
		(*L)->tag = ATOM;
		(*L)->a.atom = S.ch[0];
		(*L)->tp = NULL;
	}
	else /* 创建一般表 */
	{
		(*L)->tag = LIST;
		(*L)->tp = NULL;
		SubString(&sub, S, 2, StrLength(S) - 2); /* 脱外层括号 */
		sever(&sub, &hsub); /* 从sub中分离出表头串hsub */
		CreateGList(&(*L)->a.hp, hsub);
		p = (*L)->a.hp;
		while (!StrEmpty(sub)) /* 表尾不空,则重复建n个子表 */
		{
			sever(&sub, &hsub); /* 从sub中分离出表头串hsub */
			CreateGList(&p->tp, hsub);
			p = p->tp;
		};
	}
	return OK;
}

void DestroyGList(GList *L)
{ /* 初始条件: 广义表L存在。操作结果: 销毁广义表L */
	GList ph, pt;
	if (*L) /* L不为空表 */
	{ /* 由ph和pt接替L的两个指针 */
		if ((*L)->tag) /* 是子表 */
			ph = (*L)->a.hp;
		else /* 是原子 */
			ph = NULL;
		pt = (*L)->tp;
		free(*L); /* 释放L所指结点 */
		*L = NULL; /* 令L为空 */
		DestroyGList(&ph); /* 递归销毁表ph */
		DestroyGList(&pt); /* 递归销毁表pt */
	}
}

Status CopyGList(GList *T, GList L)
{ /* 初始条件: 广义表L存在。操作结果: 由广义表L复制得到广义表T */
	if (!L) /* L空 */
	{
		*T = NULL;
		return OK;
	}
	*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.hp, L->a.hp); /* 复制子表 */
	if (L->tp == NULL) /* 到表尾 */
		(*T)->tp = L->tp;
	else
		CopyGList(&(*T)->tp, L->tp); /* 复制子表 */
	return OK;
}

int GListLength(GList L)
{ /* 初始条件: 广义表L存在。操作结果: 求广义表L的长度,即元素个数 */
	int len = 0;
	GList p;
	if (L->tag == LIST && !L->a.hp) /* 空表 */
		return 0; /* 空表返回0 */
	else if (L->tag == ATOM) /* 单原子表 */
		return 1;
	else /* 一般表 */
	{
		p = L->a.hp;
		do
		{
			len++;
			p = p->tp;
		} while (p);
		return len;
	}
}

int GListDepth(GList L)
{ /* 初始条件: 广义表L存在。操作结果: 求广义表L的深度 */
	int max, dep;
	GList pp;
	if (L == NULL || L->tag == LIST && !L->a.hp)
		return 1; /* 空表深度为1 */
	else if (L->tag == ATOM)
		return 0; /* 单原子表深度为0 */
	else /* 求一般表的深度 */
		for (max = 0, pp = L->a.hp; pp; pp = pp->tp)
		{
			dep = GListDepth(pp); /* 求以pp为头指针的子表深度 */
			if (dep > max)
				max = dep;
		}
	return max + 1; /* 非空表的深度是各元素的深度的最大值加1 */
}

Status GListEmpty(GList L)
{ /* 初始条件: 广义表L存在。操作结果: 判定广义表L是否为空 */
	if (!L || L->tag == LIST && !L->a.hp)
		return OK;
	else
		return ERROR;
}

GList GetHead(GList L)
{ /* 初始条件: 广义表L存在。操作结果: 取广义表L的头 */
	GList h;
	InitGList(&h);
	if (!L || L->tag == LIST && !L->a.hp)
	{
		printf("\n空表无表头!");
		exit(0);
	}
	h = (GList)malloc(sizeof(GLNode));
	if (!h)
		exit(OVERFLOW);
	h->tag = L->a.hp->tag;
	h->tp = NULL;
	if (h->tag == ATOM)
		h->a.atom = L->a.hp->a.atom;
	else
		CopyGList(&h->a.hp, L->a.hp->a.hp);
	return h;
}

GList GetTail(GList L)
{ /* 初始条件: 广义表L存在。操作结果: 取广义表L的尾 */
	GList T;
	if (!L)
	{
		printf("\n空表无表尾!");
		exit(0);
	}
	T = (GList)malloc(sizeof(GLNode));
	if (!T)
		exit(OVERFLOW);
	T->tag = LIST;
	T->tp = NULL;
	CopyGList(&T->a.hp, L->a.hp->tp);
	return T;
}

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

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

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


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





/* 主程序 */


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

void main()
{
	char p[80];
	GList l, m;
	HString t;
	InitString(&t);
	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);
	DeleteFirst_GL(&m, &l);
	printf("\n删除m的表头,遍历广义表m:\n");
	Traverse_GL(m, visit);
	printf("\n");
	DestroyGList(&m);
}

运行结果:

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值