广义表的定义与实现
数据结构第5章 串和广义表

5.1 串的定义和基本运算
• (4)串的连接StrCat(S,T)。 • 初始条件:串S和T存在。 • 操作结果:将串T的值连接在串S的后面。 • (5)求子串SubString(Sub,S,pos,len)。 • 初始条件:串S存在,1≤pos≤StrLength(S)且
1≤len≤StrLength(S)-pos+1。 • 操作结果:用Sub返回串S的第pos个字符起长度为len的
1≤len≤StrLength(S)-pos+1。 • 操作结果:从串S中删除第pos个字符起长度为len的子串。 • (9)串的替换StrReplace(S,T,V)。 • 初始条件:串S,T和V存在,且T是非空串。 • 操作结果:用V替换串S中出现的所有与T相等的不重叠子
串。 • (10)判断串空StrEmpty(S)。 • 初始条件:串S存在。 • 操作结果:若串S为空串,则返回1;否则返回0。
• (1)非紧凑存储。设串S="Hello boy",计算机字长为32 位(4个Byte),用非紧凑格式一个地址只能存一个字符, 如图5-2所示。其优点是运算处理简单,但缺点是存储空 间十分浪费。
• (2)紧凑存储。同样存储S="Hello boy",用紧凑格式一 个地址能存四个字符,如图5-3所示。紧凑存储的优点是 空间利用率高,缺点是对串中字符处理的效率低。
•}
5.3 串的基本运算的实现
• (3)求子串操作。求串S从第pos位置开始,长度为len的 子串,并将其存入到串Sub中。操作成功返回1,不成功 返回0。其算法描述如下:
• int SubString(String *S,String *Sub,int pos,int len)
数据结构第五章 数组与广义表

压缩存储方法:只需要存储下三角 (含对角线)上的元素。可节省一 半空间。
可以使用一维数组Sa[n(n+1)/2]作为n阶对称矩阵A的存 储结构,且约定以行序为主序存储各个元素,则在Sa[k]和矩
阵元素aij之间存在一一对应关系: (下标变换公式)
i(i+1)/2 + j 当i≥j k = j(j+1)/2 + i 当i<j
q = cpot[col];
T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i; T.data[q].e = M.data[p].e; ++cpot[col]; }
分析算法FastTransposeSMatrix的时间 复杂度:
for (col=1; col<=M.nu; ++col) … … for (t=1; t<=M.tu; ++t) … … for (col=2; col<=M.nu; ++col) … … for (p=1; p<=M.tu; ++p) … …
//对当前行中每一个非零元
处
brow=M.data[p].j;
理
if (brow < N.nu ) t = N.rpos[brow+1];
M
else { t = N.tu+1 }
的
for (q=N.rpos[brow]; q< t; ++q) { ccol = N.data[q].j; // 乘积元素在Q中列号
一、三元组顺序表
对于稀疏矩阵,非零元可以用三元组表示, 整个稀疏矩阵可以表示为所有非零元的三元组所 构成的线性表。例如:
第5章 广义表

12
例:求下列广义表操作的结果(严题集5.10②) (k, p, h) ; 1. GetTail【(b, k, p, h)】=
2. GetHead【( (a,b), (c,d) )】= 3. GetTail【( (a,b), (c,d) )】=
(c,d)
((c,d)) ;
;
4. GetTail【 GetHead【((a,b),(c,d))】】=(b) ; 5. GetTail【(e)】= 6. GetHead 【 ( ( ) )】= 7. GetTail【 ( ( ) ) 】= () ; . .
讨论:广义表与线性表的区别和联系? 广义表中元素既可以是原子类型,也可以是列表; 当每个元素都为原子且类型相同时,就是线性表。
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, , ) ) )
13
(a,b)
()
()
5.5 广义表的存储结构
由于广义表的元素可以是不同结构(原子或列表),难以用 顺序存储结构表示 ,通常用链式结构,每个元素用一个结 点表示。 注意:列表的“元素”还可以是列表,所以结点可能有两种形 式 1.原子结点:表示原子,可设2个域或3个域,依习惯而选。 法1:标志域,数值域 tag=0 标志域 value 数值域 法2:标志域、值域、表尾指针 tag=0 atom
} ADT Glist
10
基 结构的创建和销毁 InitGList(&L); DestroyGList(&L); 本 CreateGList(&L, S); CopyGList(&T, L); 操 作 状态函数
广义表的应用课程设计

广义表的应用课程设计一、课程目标知识目标:1. 理解广义表的定义和基本概念;2. 学会使用广义表表示复杂的线性结构;3. 掌握广义表的基本操作,如创建、插入、删除、查找等;4. 能够运用广义表解决实际问题。
技能目标:1. 能够运用广义表的基本操作,实现线性结构的存储和运算;2. 能够分析实际问题,选择合适的广义表结构进行建模;3. 能够编写简单的程序,利用广义表解决具体问题;4. 培养学生的逻辑思维能力和编程实践能力。
情感态度价值观目标:1. 培养学生对数据结构和算法的兴趣,激发学习热情;2. 培养学生的团队协作意识和解决问题的能力;3. 培养学生面对复杂问题,勇于尝试、积极探究的精神;4. 增强学生的自信心和成就感,鼓励他们发挥创新精神。
课程性质:本课程为计算机科学领域的数据结构与算法课程,旨在帮助学生掌握广义表这一数据结构,并运用其解决实际问题。
学生特点:学生具备一定的编程基础,对数据结构有一定了解,但可能对广义表的认识较为陌生。
教学要求:结合学生特点,注重理论与实践相结合,通过实例讲解、课堂互动、上机实践等环节,使学生掌握广义表的应用。
同时,关注学生的情感态度,激发学习兴趣,培养其解决问题的能力和团队协作精神。
在教学过程中,将课程目标分解为具体的学习成果,以便于教学设计和评估。
二、教学内容1. 广义表的定义与基本概念:- 线性表、广义表的概念与区别;- 广义表的元素、表头、表尾及表长等基本概念。
2. 广义表的存储结构:- 顺序存储结构;- 链式存储结构。
3. 广义表的基本操作:- 创建广义表;- 插入、删除、查找等操作;- 广义表的遍历。
4. 广义表的应用:- 利用广义表解决实际问题,如多项式的表示与运算;- 广义表在数据压缩中的应用;- 广义表在计算机图形学中的应用。
5. 教学案例与上机实践:- 结合实际案例,分析广义表的应用场景;- 上机实践,编写程序实现广义表的基本操作;- 团队协作,共同探讨广义表在解决复杂问题中的应用。
数据结构广义表

结点结构是无论什么结点都有三个域:
第一个域是结点类型标志tag; 第二个域是指向一个列表的指针(当tag=1时) 或一个原子(当tag=0时); 第三个域是指向下一个结点的指针tp。
3 广义表的存储结构
形式描述为:
typedef enum{ ATOM, LIST }ElemTag typedef struct GLNode { //定义广义表结点 ElemTage tag; //公共部分,用以区分 原子结点和表结点 Unin{ //原子结点和表结点的联合部分 AtomType atom;//原子类型结点域, // AtomType由用户定义 struct GLNode *hp,; //表结点的表头指针域 }; struct GLNode *tp; //指向下一个结点的指针 }*Glist; //广义表类型
5. E=(a,E)
这是一个递归列表,其元素中有自己。
广义表也可以用图形表示,例如前述的广义表D和E可表示为:
广义表D
D
广义表E
E
C
A
B
a
e
a b c d
2 广义表的基本运算
广义表的基本运算 ⑴ 取表头 HEAD(LS); ⑵ 取表尾 TAIL(LS)。
3 广义表的存储结构
广义表中的数据元素可以是单元素,或是广义表, •很难用顺序存储结构表示,常采用链式存储结构。 1.表头表尾链存储结构 有两类结点:表结点和单元素结点。
P 1 3 1 1
A=y((c,3),(D,2)) C=x((1,10),(2,6))
^
1 2
A
z y 1 1 1 3
C
x 0 0 15 ^
B
1 2
1 2
^
广义表及本章小结

2 .广义表的同层结点链存储结构 在这种结构中,无论是单元素结点还是子表结点均由三个域构成。其结点结 构如下图所示。
tag=1 hp tp
表结点
tag=0 atom tp
原子结点
广义表的同层结点链结点结构
广义表 A、 B、 C、 D 的扩展线性链表存储结构如下图所示。
D 1 ∧∧
A
1
∧
0a
1
∧
B
1
第 5 讲 广义表及本章小结——教学讲义 广义表,也是线性表的一种推广。它被广泛的应用于人工智能等领域的表处 理语言 LISP 语言中。在 LISP 语言中,广义表是一种最基本的数据结构,LISP 语言 编写的程序也表示为一系列的广义表。
一、 广义表的概念
在第 2 章中,线性表被定义为一个有限的序列( a1 ,a2 ,a3 ,…, an),其中 ai 被限定 为是单个数据元素。广义表也是 n 个数据元素( d1 ,d2 ,d3 ,…, dn)的有限序列,但不 同的是,广义表中的 di 既可以是单个元素,还可以是一个广义表,通常记做: GL =( d1 ,d2 ,d3 ,…, dn)。 GL 是广义表的名字,通常广义表的名字用大写字母表示。 n 是广义表长度。若其中 di 是一个广义表,则称 di 是广义表 GL 的子表。在广义表 GL 中,d1 是广义表表头,而广义表 GL 其余部分组成的表( d2 ,d3 ,…, dn)称为广义表 表尾。由此可见广义表的定义是递归定义的,因为在定义广义表时又使用了广义 表的概念。下面给出一些广义表的例子,以加深对广义表概念的理解。 D=() 空表;其长度为零。 A=(a,(b,c)) 表长度为 2 的广义表,其中第一个元素是单个数据 a,
A[i][j] f B[K]
广义表知识点总结

广义表知识点总结一、广义表的概念和基本操作1.1 概念广义表是一种递归定义的数据结构,它可以包含原子元素和其他广义表,类似于树的结构。
广义表在计算机科学中广泛应用,常用于表示复杂的数据结构和递归算法。
1.2 基本操作广义表的基本操作包括创建、插入、删除、查找等,通过这些操作可以对广义表进行灵活的操作和管理。
在实际应用中,需要根据具体的需求对广义表进行不同的操作。
二、广义表的存储结构2.1 顺序存储结构顺序存储结构是将广义表中的元素按照顺序存储在内存中的一片连续空间中,可以通过下标访问元素,适合于对广义表进行随机访问的场景。
2.2 链式存储结构链式存储结构是通过指针将广义表中的元素连接起来,每个元素包含指向下一个元素的指针,适合于对广义表进行插入和删除操作的场景。
2.3 各种存储结构的比较在选择广义表的存储结构时,需要根据实际应用场景和需求来进行选择,顺序存储结构适合于对广义表进行随机访问,链式存储结构适合于对广义表进行插入和删除操作。
三、广义表的操作和应用3.1 创建广义表创建广义表可以通过递归的方式来实现,对于包含原子元素和子表的广义表,需要递归地创建子表并将它们链接起来。
3.2 插入和删除元素对于顺序存储结构的广义表,可以通过数组的插入和删除操作来实现元素的插入和删除;对于链式存储结构的广义表,可以通过修改指针来实现元素的插入和删除。
3.3 查找元素查找元素可以通过顺序遍历的方式来实现,对于包含子表的广义表,需要递归地进行遍历。
3.4 应用场景广义表在计算机科学中具有广泛的应用场景,包括对树的表示和操作、对图的表示和操作、对复杂数据结构的表示和操作等。
四、广义表的递归算法4.1 递归算法概念递归算法是指在解决问题的过程中,通过调用自身来处理子问题,直到子问题为空或者达到终止条件为止。
广义表的表示和操作通常涉及到递归算法。
4.2 广义表的递归遍历对于包含子表的广义表,需要通过递归算法来实现遍历操作,递归地对子表进行遍历,直到遍历到最底层的子表。
《数据结构(Python语言描述)》第5章 广义表

广义表是由n个类型相同的数据元素(a1、a2、……、an)组成的有限序列。广义表的元素可以是单个 元素,也可以是一个广义表。通常广义表记作:
GL=(a1,a2,…,an) 广义表有两种数据元素,分别是原子和子表,因此需要两种结构的节点,一种是表节点,用来表 示子表,如图5-1所示;一种是原子节点,用来表示原子,如图5-2所示。
OPTION
在广义表GL中,如果ai也是一个 广义表表,则称ai为广义表GL的 子表。
03 表头
OPTION
在广义表中GL中,a1如果不为空, 则称a1为广义表的表头。
04 表尾
OPTION
在广义表GL中,除了表头a1的其余 元素组成的表称为表尾。
05 深度
OPTION
广义表GL中括号嵌套的最大层数。
图5-3 广义表表节点
表节点由三个域组成:标志域tag,指向表头节点的指针域ph,指向表尾节 点的指针域pt。表节点的标志域tag=1。
5.3 存储结构
7
图5-4 广义表原子节点
原子节点由两个域组成:标志域tag,值域atom。原子节点的标志域tag=0。
节点的定义:
class Node:
def __init__(self, ph, pt, tag, atom):
表节点由三个域组成,即标志域tag、指向表头节点的指针域ph、指向表尾节点的指针域pt。表节点 的标志域tag=1。
原子节点由两个域组成,即标志域tag、值域atom。原子节点的标志域tag=0。
5.2 基本用语
4
01 原子
OPTION
在广义表GL中,如果ai为单个元 素,则称ai称为原子
02 子表
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
5.1.2 举例
分别用圆圈和方框表示表(表元素)和单元素 ①A=() 空表,其长度为零。
②B=(e) B中只有一个单元素,长度为1,表头为'e',表尾为 空。
③C=(a,(b,c,d)) 长度为2,表头为‘a’,表尾为子表((b,c, d))。
④D=(A,B,C) 长度为3,表头为A, 表尾为(B,C)。
⑤E=(a,E) 长度为2,表头为a,表尾为(E)--表头为E,表尾为 ()。E相当于无穷表(a,(a,(a,(…))))。
5.1.3广义表的几个性质
①有次序性: 广义表中的数据元素有固定的相对次序。 线性排列 --线性表的推广 层次结构 --树的推广 ②有长度: 广义表的长度定义为最外层括弧中包含的数 据元素个数。 表元素个数一定,不能无限,可以是空表。
⑶ 求广义表的深度 int getDepth(GList L) //采用头尾链表存储结构,求广义表L的深度 { int max=0,dep; GList p; if(!L) return 1; //空表深度为1 if(L->tag==ATOM) return 0; //原子深度为0 for(p=L; p; p=p->ptr.tp) { dep=getDepth(p->ptr.hp); //求以p->a.ptr.hp为头指针的子表深度 if(dep>max) max=dep; } return max+1; // 非空表的深度是各元素的深度的最大值加1 }
tag=0 atom
原子结点
tag=1
ptr---表结点的指针域 hp tp
表结点
广义表的头尾链表存储表示:
enum ElemTag {ATOM,LIST}; typedef char AtomType;
struct GLNode{ ElemTag tag; union { AtomType atom; struct { GLNode *hp,*tp; } ptr; }; };
if(i<n) { hstr=str.substr(1,i-2); str="("+str.substr(i,n-i); } else { hstr=str.substr(1,n-2); str=""; } return hstr;
}
S的值有三种情况: ①"( )"--空表 ②单字符串--原子结点 ③多字符串--列表
④((x,y),((z)))的表头为列表(x,y)
其余分析同上。
ቤተ መጻሕፍቲ ባይዱ
5.2 广义表操作的实现
基于广义表是递归定义的结构,因此实现广 义表操作的算法均为递归函数。
5.2.1 分治法与递归求解
分治法是进行算法设计的一种方法,其严格定义为: 对于一个输入规模为 n 的函数或问题,用某种 方法把输入分割成 k(1<k≤n) 个子集,从而产生m个 子问题,分别求解这m个问题,得出m个问题的子 解,再用某种方法把它们组合成原来问题的解。若 子问题还相当大,则可以反复使用分治法,直至最 后所分得的子问题足够小,以至可以直接求解为止。 在利用分治法求解时,若所得子问题的性质和原问 题相同,则可递归求解。
if(L->ptr.tp) { cout<<','; printGList(L->ptr.tp,1); } if(k==0) cout<<')'; } else cout<<L->atom; } }
5.2.4 应用
main.cpp
#include "glist.h" int main(){ string S1="((),(e),(a,(b,c,d)))"; string S2="(a,(x,y),((z)))"; string S3="(a,b)"; string S4="()"; GList L; initGList(L); creatGList(L,S2); cout<<getLength(L)<<endl; cout<<getDepth(L)<<endl; printGList(L); }
typedef GLNode* GList;
例:广义表 L=(a,(x,y),((z))) 的存储结构。
可由对L进行表头和表尾的分析得到--若列表不空, 则可分解成表头和表尾(采用头尾链表存储结构)。 分析: ①L为一非空列表
②L的表头为原子a
③L的表尾为列表((x,y),((z)))
// 将非空串str分割成两部分: // hsub为最外层第一个','之前的子串,str为之后的子串
string sever(string& str) { int n,k,i; // k记录尚未配对的左括号个数 string ch,hstr; n=str.length(); for(i=0,k=-1; i<n&&(ch!=","||k!=0); ++i) { // 搜索最外层的第一个逗号 ch=str.substr(i,1); //从第i个位置起,取1个字符 if(ch=="(") ++k; else if(ch==")") --k; }
何谓"递归函数"?
一个含直接或间接调用本函数语句的函数被 称之为递归函数,它必须满足以下两个条件: ①在每一次调用自己时,必须是(在某种意义 上)更接近于解; ②函数中必须有一个终止处理或计算的准则。
5.2.2 广义表的头尾链表存储表示
glist.h #include <iostream> #include <string> using namespace std;
} }
⑸ 以字符串形式输出广义表 void printGList(GList& L,int k) // 利用递归算法输出广义表L { if(!L) cout<<"()"; else { if(L->tag==1) { if(k==0) cout<<'('; if(L->ptr.hp==NULL) cout<<"()"; else printGList(L->ptr.hp,0);
⑷ 建立广义表 以广义表字符串S建立广义表。 从前面的讨论可知,非空广义表可分解成表头和表 尾两个部分。建表时,可分别建立(分解为两个子 问题): 表头有两种情况,为单原子或为列表,当为列表时 与原问题相同; 表尾必为列表,与原问题相同。 设string sever(string& S )函数的功能为: 从广义表字符串S中提取表头串返回,并将S置成表 尾串。
//由广义表的书写形式串S创建广义表L
void creatGList(GList& L,string S) { string hsub; if(S=="()") L=NULL; //创建空表 else { L=new GLNode; //建表结点 if(S.length()==1) //S为单原子 { L->tag=ATOM; L->atom=S[0]; //创建单原子广义表 }
第5章 广义表
5.1 广义表的定义 5.2 广义表操作的实现
5.1 广义表的定义
5.1.1 定义
广义表(Lists)简称表,它是线性表的推广。 一个广义表是n(n≥0)个元素的序列,当 n=0时称为空表。在一个非空的广义表中,其 元素可以是某一确定类型的对象(这种元素 被称作单元素),也可以是由单元素构成的 表(这种元素可相对地被称作子表或表元 素)。显然,广义表的定义是递归的,广义 表是一种递归的数据结构。
③有深度: 广义表的深度(多少层)定义为广义表书写 形式中括弧的最大重数,因此空表的深度为1, 因为一个"单原子"不是广义表,所以没有"深 度"可言,但可以认为它的深度为0。 如:A,B:1;C:2;D:3; E:无穷大。 ④可递归: 如E。 ⑤可共享: 子表可共享。
5.1.4 广义表的存储结构
5.2.3 操作的实现
glist.cpp
#include "glist.h" ⑴ 初始化 void initGList(GList& L) { L=NULL; }
//创建空的广义表L
⑵ 求广义表的长度 int getLength(GList L) //返回广义表的长度,即元素个数 { if(!L) return 0; else return 1+getLength(L->ptr.tp); }
设ai为广义表的第i个元素,广义表LS可表示为: LS=(a1,a2,…, an) 其中: ①LS——广义表的名字; ②n——广义表的长度; 或者是单元素 (小写) ③ ai--表中的元素 ; 或者是表元素 (大写) ④n=0 空表; ⑤当广义表非空时,称a1为表头(head),其余元素组 成的表(a2,a3, …, an)为表尾(tail); 广义表的抽象数据类型:P107