广义表的链式存储结构
广义表的存储结构

广义表的存储结构广义表是一种表示数据结构的层次形式。
广义表的数据结构具有弹性,可以用来表示任意复杂度的对象,广泛应用于计算机科学中,在许多普通的程序设计语言中,这是一种重要的数据类型。
简而言之,它可以表示更复杂的结构,例如树形结构和图形结构。
广义表是一种递归结构,它由多个元素构成。
一个广义表的元素可以是一个基本的值,也可以是一个广义表,表示下一级的数据结构。
基本元素可以是任何数据类型,而广义表的元素可以是任意复杂度的数据结构。
因此,广义表用来表示任意复杂度的数据结构有着十分强大的表示能力,成为一种强大的数据结构表示方式。
当处理广义表的存储问题时,需要考虑到其数据的特点,只有当特点被有效考虑到时,储存和操作广义表才能更有效地实现。
为了实现更有效的存储,一般有三种方式可以考虑:链式储存、双亲表示法和结点表示法。
链式储存是一种比较简单的方式,把广义表的每个元素都以链表的形式存储下来,这种方式可以方便地查找元素,操作形式也比较简单,但是因为引入了指针,而且每个结点只有一个指针,所以存储空间利用率低,不够高效。
双亲表示法是利用普通表表示广义表的一种方式,它把广义表的每个元素都储存在一个有限的表格中,每个元素的表格包括元素的值、子节点的位置、双亲节点的位置等,以此来表示广义表的结构关系。
双亲表示法的优点是其存储效率高,把每个元素的值和其结构关系存储在一张表中,存储空间利用率比较高,但是它的查找和操作效率比较低,需要大量的遍历操作。
结点表示法是另一种表示广义表的方式,它把广义表的每个元素都储存在一个节点中,每一个节点中包含元素的值,以及指向该元素的子节点和双亲节点的指针,因此可以表示出广义表的层次结构。
结点表示法既可以查找结点和操作结点,又能存储元素的值和结构关系,所以其存储空间利用率较高,查找和操作也比较快,比较灵活。
总之,当处理广义表的存储问题时,可以通过链式储存、双亲表示法和结点表示法来实现更有效的存储,其中结点表示法比较灵活,在存储空间利用率上要优于其他方法。
数据结构与算法问题分析及源代码之广义表

广义表1 题目编写一个程序,实现广义表的各种运算,并在此基础上设计一个程序完成如下功能:建立广义表g=“(b,(b,a),((a,b),c))”的链式存储结构。
输出广义表g的长度。
输出广义表g的深度。
2 目标熟悉广义表的定义及其基本操作的实现3 设计思想链式存储的广义表,结点包含数据区,指针,以及一个标记头结点的整型数。
广义表的表示结构为:(a,b),其中a、b可以是字符或广义表。
因此,可以用递归算法来实现对它的定义与操作。
4 算法描述(1)创建广义表:逐个输入表示广义表的字符串,以‘(’为起始标志建立结点并标记为头结点,递归调用此操作建立广义表;若读入‘)’则将最后结点的指针置空;读入非结束字符,赋值到结点数据区,并赋值指针形链式结构,两个结点之间打印‘,’。
(2)求广义表长度:广义表基本组成元素(a,b)若a、b不是广义表则(a,b)深度为一。
广义表的深度等于表头结点的数量,从表头结点遍历广义表,对每一个广义表结点应用该函数,若tag==1(结点是表头)则返回计数器加一,否则返回0。
(3)输出广义表:从表头开始,测试结点指针,若指针指向结点的标记位为1,则先打印‘(’再输出其数据值,并调用该操作输出下一个结点;函数返回时,测试指针指向结点的标记位,若为1,则先打印‘)’,再调用该函数输出下一个结点数据;每次输出数据值以后测试该结点是否为子广义表的最后一个结点,不是则输出‘,’,否则返回。
5 程序结构图6 源程序#include<iostream.h>#include<malloc.h>#include <stdio.h>typedef struct lnode{int tag;union{char atom;struct lnode *p;}ptr;struct lnode *q;}Lnode;Lnode *CreatGL(){ // 创建一个广义表,表中元素为字符Lnode *h;char ch;ch=getchar();if(ch){h=(Lnode*)malloc(sizeof(Lnode)); //为表分配内存空间if(ch=='('){h->tag=1;h->ptr.p=CreatGL(); //用递归的方法实现创建广义表的操作}else if(ch==')')h=NULL;else{h->tag=0;h->ptr.atom=ch;}}else h=NULL;ch=getchar();if(h!=NULL)if(ch==',')h->q=CreatGL();elseh->q=NULL;return h;}int GLLength(Lnode *g){ // 求广义表的长度int n=0;g=g->ptr.p;while(g){n++;g=g->q;}return n;}int GLDepth(Lnode *g){ // 求广义表的深度int max=0,dep;if(g->tag==0)return 0;g=g->ptr.p;if(g==NULL)return 1;while(g){if(g->tag==1){dep=GLDepth(g);if(dep>max)max=dep;}g=g->q;}return (max+1);}void DispGL(Lnode *g){ // 输出广义表if(g){if(g->tag==1){cout<<"(";if(g->ptr.p==NULL)cout<<" ";elseDispGL(g->ptr.p);}elsecout<<g->ptr.atom;if(g->tag==1)cout<<")";if(g->q){cout<<",";DispGL(g->q);}}else cout<<"广义表不存在"<<endl; }#include <stdio.h>#include <stdlib.h>#include<iostream.h>#include"glist.h"int main(){char choice;Lnode *glist;cout<<"键入广义表:"<<endl;glist=CreatGL();system("cls");printf("请选择(输入0退出)\n1 输出广义表内容\n2 输出广义表长度\n3 输出广义表深度\n");cout<<endl<<"选择:";cin>>choice;while(choice!='0'){system("cls");printf("请选择(输入0退出)\n1 输出广义表内容\n2 输出广义表长度\n3 输出广义表深度\n");switch (choice){case '1':DispGL(glist);cout<<endl;break;case '2':cout<<"广义表的长度为: "<<GLLength(glist) <<endl;break;case '3':cout<<"广义表深度为:"<<GLDepth(glist)<<endl;break;case '0':return 0;}cout<<endl<<"选择:";cin>>choice;}。
数据结构之第8章 广义表

3. 建立广义表的链式存储结构
假定广义表中的元素类型ElemType为char类型,
每个原子的值被限定为英文字母。
并假定广义表是一个表达式,其格式为:元素之
间用一个逗号分隔,表元素的起止符号分别为左、右
圆括号,空表在其圆括号内不包含任何字符。例如
“(a,(b,c,d))”就是一个符合上述规定的广义表格式。
/*广义表结点类型定义*/
广义表的两种基本情况 :
g2 1
∧
g1
1
∧
∧*Βιβλιοθήκη * 第 1 个元素**
…
*
*
∧
第 2 个元素
第 n 个元素
(a)空表
(b)非空表
为原子的情况 :
g3 0 a
∧
8.3 广义表的运算
1. 求广义表的长度 在广义表中,同一层次的每个结点是通过link域
链接起来的,所以可把它看做是由link域链接起来的
{ h->tag=1;
/*新结点作为表头结点*/
h->val.sublist=CreatGL(s); /*递归构造子表并链到表头结点*/ }
else if (ch==')') h=NULL; /*遇到')'字符,子表为空*/ else { h->tag=0; /*新结点作为原子结点*/ h->val.data=ch; } } else h=NULL; ch=*s; s++; if (h!=NULL) if (ch==',') h->link=CreatGL(s); else h->link=NULL; return h; }
单链表。这样,求广义表的长度就是求单链表的长度,
内容提要广义表的概念广义表的存储结构广义表的课件

❖ template <class T> ❖ int GList<T>::Depth() ❖ { return Depth(head); }
2024/7/17
6. 广义表的析构算法 (递归)
• template <class T>
• void GList<T>::Free(GListNode<T> *p)
• { if (p==NULL) return;
• q=p;
// q指向待释放结点
• p=p->sublist; // p指向第一个结点
• delete q;
•
2024/7/17
❖ while( p )
❖ { q=p; // q指向待释放结点
❖
p=p->next; // p指向下一个结点
❖
if (q->type==ATOM) delete q;
❖
else Free(q);
❖}
❖}
❖ template <class T>
❖ GList<T>::~GList()
❖ { Free(head); }
2024/7/17
本章小结
❖ (1)掌握广义表的定义。 ❖ (2)重点掌握广义表的存储结构。 ❖ (3)掌握广义表的基本运算,
包括创建广义表、释放广义表、遍历广义表、 求广义表的长度和深度。
例如: A=() B = (a, b, c) C = (a, (b, c, d), e) D = ((a, b), c, (d, (e, f), g) ) E = (a, ( ), (( ), ( )), b) L=(a, (a, b), (a, (a, b), c), ( ))
广义表的单链表示

广义表的单链表示是一种数据结构,它采用链式存取方式,利用结点的方式表示数据。
在这一数据结构中,每个结点由一个元素和一个指向其他结点的指针组成。
单链表的创建有两种方法,分别是头插入法和尾插入法。
头插入法的效果是使得整个链表的元素逆序,而尾插入法则能够保证结点次序与输入数据保持一致。
我们以一个简单的例子来说明如何进行广义表的单链表示。
假设我们有一个名为"A,B"的广义表,表示元素为"A"和"B"的两个元素组成的集合。
这个广义表可以转换成一个单链表来进行存储。
首先,我们可以创建两个空结点,分别表示"A"和"B"的元素,并且在每个结点上设置一个指向下一个结点的指针。
例如,我们可以将第一个结点设置为指向第二个结点的指针,而将第二个结点设置为指向空的指针。
然后,我们可以使用尾插入法将"A"和"B"这两个元素依次插入到链表的尾部。
这就需要我们不断地使用递归的方法,将当前结点插入到链表的尾部。
在每一次递归中,我们都需要递增一个指针来指向当前结点的下一个结点。
当我们完成整个插入操作后,整个链表的结构将类似于一个无穷的链表,其中"A"和"B"分别在链表的首尾两个位置。
值得注意的是,由于广义表的元素可能是多元组或者无穷集,因此单链表的长度和深度也可能是无限的。
这就需要我们在实现单链表的操作时,需要进行一些特殊的处理。
例如,我们可以使用栈或者树等数据结构来管理结点的插入和删除操作。
总之,广义表的单链表示是一种非常实用的数据结构,它能够有效地表示和管理无穷集和多元组等复杂数据。
通过采用单链表的结构,我们能够方便地进行元素的插入、删除、查找等操作,并在需要时进行递归处理。
第5章广义表

数据结构
else h=NULL; ch=*(*s); (*s)++; if(h!=NULL) if(ch==',') h->link =creat_GL(s); else h->link=NULL; return(h); }
该算法的时间复杂度为O(n)。
数据结构
2.输出广义表prn_GL(p) 对于广义表的表头结点p,若为表结点,输出空表或递归 输出子表的内容,否则,输出元素值;若当前的结点还有 后续结点,则递归输出后续表的内容。 下面的函数把按链接存储的广义表以字符串形式输出。 void prn_GL(NODE *p) { if(p!=NULL) { if(p->tag==1) { printf("("); if(p->dd.sublist ==NULL) printf(" "); 数据结构
5.取表尾运算tail .取表尾运算 若广义表LS=(a1 ,a2 ,…,an),则tail(LS)=(a2 ,a3 ,…, an)。 即取表尾运算得到的结果是除表头以外的所有元素,取 表尾运算得到的结果一定是一个子表。 值得注意的是广义表( )和(())是不同的,前者为空表,长 度为0,后者的长度为1,可得到表头、表尾均为空表, 即head((( )))=( ),tail((( )))=( )。 数据结构
四、几个运算的调用
下列主函数的功能是:创建带表头结点链式存储的广义表 然后复制一个新的广义表,并把广义表按字符串的方式 输出. main() { NODE *hd,*hc; char s[100],*p; p=gets(s); hd=creat_GL(&p); hc=copy_GL(hd); printf("copy after:"); prn_GL(hc); }
c语言 广义表

C语言广义表1. 什么是广义表?广义表(Generalized List),简称GList,是一种线性链表的扩展结构,也是一种特殊的树结构。
与传统的线性链表不同,广义表的节点可以存储原子数据和子表(也就是另一个广义表)。
在C语言中,可以使用指针和结构体来实现广义表。
每个节点包含两个指针域,分别指向下一个节点和子表。
通过这种方式,可以灵活地表示复杂的数据结构。
2. 广义表的表示方法广义表有两种常用的表示方法:括号表示法和逻辑列表法。
2.1 括号表示法括号表示法使用括号来标识子表,并用逗号分隔元素。
例如,(1, (2, 3), (4, (5, 6)))表示一个包含三个元素的广义表,其中第一个元素是原子数据1,第二个元素是一个包含两个原子数据2和3的子表,第三个元素是一个包含两个原子数据4和另一个包含两个原子数据5和6的子表。
2.2 逻辑列表法逻辑列表法使用空格或其他特殊符号来分隔元素,并用一对方括号将所有元素括起来。
例如,[1, [2 3], [4 [5 6]]]表示同样的广义表。
3. 广义表的操作广义表支持一系列的操作,包括创建、插入、删除、查找等。
3.1 创建广义表可以通过递归的方式创建广义表。
首先创建一个节点,然后判断当前元素是原子数据还是子表。
如果是原子数据,则将其存储在节点中;如果是子表,则递归创建子表并将其存储在节点中。
3.2 插入元素插入元素可以分为两种情况:在指定位置前插入一个新元素和在指定位置后插入一个新元素。
在指定位置前插入一个新元素时,需要先找到要插入位置的前一个节点,然后创建一个新节点,并将新节点的指针域指向要插入位置的节点,再将要插入位置的前一个节点的指针域指向新节点。
在指定位置后插入一个新元素时,需要先找到要插入位置的节点,然后创建一个新节点,并将新节点的指针域指向要插入位置的下一个节点,再将要插入位置的节点的指针域指向新节点。
3.3 删除元素删除元素也可以分为两种情况:删除指定位置上的元素和删除指定值的元素。
第五章 广义表

广义表是递归 递归定义的线性结构 线性结构, 递归 线性结构
LS = ( α1, α2, ⋅⋅⋅, αn ) 其中:αi 或为原子 或为广义表
例如: 例如 A = ( ) F = (d, (e)) D = ((a,(b,c)), F) C = (A, D, F) B = (a, B) = (a, (a, (a, ⋅⋅⋅ , ) ) )
1 0 a
1
∧
0 d
广义表的存储结构示意图 图5-14 广义表的存储结构示意图
在这种存储结构中有几种情况: 这种存储结构中有几种情况: 这种存储结构中有几种情况 (1)除空表的表头指针为空外,对任何非空列表,其 表头指针均指向一个表结点,且该结点中的hp域指示 列表表头(或为原子结点,或为表结点),tp域指向列 表表尾(除非表尾为空,则指针为空,否则必为表结 点); (2)容易分清列表中原子和子表所在层次。如在列表 D中,原子a和e在同一层次上,而b、c和d在同一层次 且比a和e低一层,B和C是同一层的子表; (3)最高层的表结点个数即为列表的长度。以上三个 特点在某种程度上给列表的操作带来方便。
表5-2
广 义 表
广义表及其示例 广义表及其示例
表长n 表深h 表深
D A e B a b c d C 0 1 2 3 ∞
A=() B=(e) C=(a,(b,c,d)) D=(A,B,C) E=(a,E)
0 1 2 3 2
广义表的图形表示 图 广义表的图形表示
例2:试用图形表示下列广义表. 试用图形表示下列广义表.
void hanoi (int n, char x, char y, char z) {//y为辅助塔 为辅助塔 if (n==1) move(x, 1, z); else { hanoi(n-1, x, z, y); move(x, n, z); hanoi(n-1, y, x, z); } }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
广义表是一种扩展了线性表的数据结构,它可以包含其他广义表作为其元素,形成树状结构。
广义表的链式存储结构通常采用链表来表示,这样便于处理不同长度的子表。
下面是关于广义表链式存储结构的详细介绍:
**广义表的定义:**
广义表是线性表的推广,可以包含元素和子表。
一个广义表可以为空表,也可以是一个单一元素或由若干元素和子表组成的序列。
**链式存储结构:**
在链式存储结构中,广义表的每个元素都由一个节点表示,节点中包含两个域:数据域和指针域。
数据域用来存储元素的值,而指针域则指向下一个节点,形成链表。
对于广义表的节点,数据域可以是一个基本元素,也可以是另一个广义表。
**节点定义示例:**
```python
class Node:
def __init__(self, data):
self.data = data
self.next = None
```
**广义表链式存储的构建:**
广义表的链式存储结构可以通过递归方式进行构建。
每个节点的数据域可以是基本元素,也可以是一个新的广义表。
```python
# 示例:构建广义表(a, b, (c, d), e)
a_node = Node('a')
b_node = Node('b')
c_node = Node('c')
d_node = Node('d')
e_node = Node('e')
# 构建子表(c, d)
sublist_node = Node(c_node)
c_node.next = Node(d_node)
# 构建主表(a, b, (c, d), e)
a_node.next = Node(b_node)
b_node.next = Node(sublist_node)
sublist_node.next = Node(e_node)
```
**广义表链式存储的优点:**
1. **灵活性:** 链式存储结构允许广义表的元素包含不同长度的子表,使得数据结构更加灵活。
2. **动态性:** 链表的动态特性使得广义表的大小可以根据实际需要动态调整,不受固定大小的限制。
3. **易于处理不同元素类型:** 数据域可以容纳基本元素和广义表,使得广义表可以容纳不同类型的元素。
**广义表链式存储的缺点:**
1. **空间开销:** 由于需要存储指针信息,链式存储结构相对于顺序存储结构可能会占用更多的存储空间。
2. **访问效率:** 相对于顺序存储结构,链式结构在访问时需要通过指针进行跳跃,可能导致访问效率较低。
总体而言,广义表的链式存储结构是一种灵活且动态的数据表示方式,适用于需要处理复杂结构的场景。