/* 广义表的扩展线性链表存储表示 */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;elsereturn 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; /* 复制单原子 */elseCopyGList(&(*T)->a.hp, L->a.hp); /* 复制子表 */if (L->tp == NULL) /* 到表尾 */(*T)->tp = L->tp;elseCopyGList(&(*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;elsereturn 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;elseCopyGList(&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);
}

运行结果:

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

  1. 广义表的存储结构--头尾链表存储表示/扩展线性链表存储表示

    //广义表的存储结构 //1.头尾链表存储表示 typedef enum {ATOM,LIST} ElemTag;//0:原子,1:子表 typedef struct GLNode {     Ele ...

  2. 输入广义表建立子女兄弟链表示的树

    全部代码: #include<iostream> #include<string> #include<vector> #include<stack> # ...

  3. 广义表的链式定义和基础操作

    广义表的定义 广义表(Lists,又称列表)是线性表的推广.线性表定义为n>=0个元素a1,a2,a3,-,an的有限序列.线性表的元素仅限于原子项,原子是作为结构上不可分割的成分,它可以是一个 ...

  4. 【数据结构】广义表的基本概念

    广义表的基本概念 广义表不是考试的重点,只要理解基本概念就行了. 书上介绍的广义表,我觉得简单来理解的话就是狭义的列表,因为书上规定了列表的表头可以是原子或者子表,但是表尾必须是子表,在python中 ...

  5. 数组、特殊矩阵、稀疏矩阵、广义表

    文章目录 一.数组 基本知识 存储方式及地址计算 一维数组 地址计算 二维数组 地址计算 例题 例一 例二 二.特殊矩阵 对称矩阵 地址计算 三.稀疏矩阵 三元组 三元组顺序表 稀疏矩阵转置算法 算法 ...

  6. 数据结构之广义表的相关知识点

    一,广义表的基本概念: 广义表(Lists,又称列表)是一种非线性的数据结构,是线性表的一种推广.即广义表中放松对表元素的原子限制,容许它们具有其自身结构(即可以有子表).它被广泛的应用于人工智能等领 ...

  7. 数据结构-广义表详解(类C语言版)

    目录 广义表的概念 定义 表头 表尾 例 广义表的性质 广义表与线性表的区别 广义表的存储结构 头尾链表的存储结构 扩展线性链表的存储结构 ​ 广义表的基本运算 例 广义表的概念 定义 广义表通常记作 ...

  8. 数据结构(串、数组和广义表)

    串.数组和广义表 1.串 ①.串的定义 ②.串的顺序存储 ③.串的链式存储 ④.串的模式匹配算法 2.数组 ①.数组的定义 ②.数组的顺序存储 ③.特殊矩阵的压缩存储 3.广义表 ①.广义表的定义 ② ...

  9. 广义表及其存储方式简介

    广义表(Lists,又称列表)是线性表的推广.线性表定义为n>=0个元素a1,a2,a3,-,an的有限序列.线性表的元素仅限于原子项,原子是作为结构上不可分割的成分,它可以是一个数或一个结构, ...

  10. 广义表的概念及存储表示

    文章目录 广义表的概念 广义表的特性 广义表的表头和表尾 广义表的链接存储表示 头尾表示法 扩展线性链表表示法 广义表的概念 广义表的定义:广义表是 n ( n ≥ 0 ) n\ (n≥0) n (n ...

最新文章

  1. Django报错:mysql ImproperlyConfigured: mysqlclient 1.3.13 or newer is required, you have 0.9.3的解决办法
  2. log.php(157),Log出现permission Denied的错误
  3. 腾讯视频下载安装链接_腾讯视频怎么上传视频
  4. 数据库半年回顾:国外波澜不惊,国内势如破竹
  5. 递归存储过程中使用cursor
  6. WCF中因序列化问题引起的异常和错误。
  7. 信息发布系统 Jquery+MVC架构开发(5) DAL层
  8. java查看已导入的证书_jdk导入证书
  9. 统一认证 ldap mysql_Centos7 Ldap统一认证部署
  10. 瓜子2019笔试java_2019秋招瓜子携程笔试题解(含题目) 点赞有offer
  11. 无线服务器功能,无线自组织互联网的用户管理——Radius服务器的功能设计与实现...
  12. 蒙特卡洛方法求圆周率
  13. 微信小程序 实现换肤功能
  14. 学生信息管理系统——错误集锦(五)
  15. Ceph的进阶使用(一)
  16. HPC平台计算软件依赖, Singularity超级简单
  17. git 使用总结(三)repo sync -m
  18. swing小区安全管理系统
  19. 程序员如何与产品撕逼
  20. VC++在局域网基于winpcap实现QQ号码IP嗅探

热门文章

  1. MATLAB实现离散傅里叶变换DFT
  2. 《一》微信小程序简介
  3. 2022最新《人工智能入门指南》全套学习教程,全网阅读量10w+
  4. Android MVVM框架搭建(一)ViewModel + LiveData + DataBinding
  5. windows server上通过关闭端口有效防治勒索病毒
  6. 必应缤纷桌面产品分析
  7. 字体,字号与尺寸对应表
  8. sop封装与dip封装的语音芯片有何区别?
  9. 大连理工大学电路计算机,大连理工大学电路计算机辅助分析实验报告精要.pdf...
  10. 关于Maven里的setting.xml下载