数据结构 第5章广义表
数据结构第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数组和广义表A

1 Status Locate(Array A,va_list ap,int &off) 2{ 3 //若ap指示的各下标值合法,则求出该元素在A中,相对地
址off
4 off=0; 5 for(i=0;i<A.dim;++i) 6 { 7 ind=va_arg(ap,int); 8 if(ind<0||ind>A.bounds[i]) return OVERFLOW; 9 off+=A.constants[i] *ind; 10 } 11 return OK; 12 }
行数 总列数,即 第2维长度 元素个数
ij
补充:计算二维数组元素地址的通式
设一般的二维数组是A[c1..d1, c2..d2],这里c1,c2不一定是0。
单个元素 长度
二维数组列优先存储的通式为: LOC(aij)=LOC(ac1,c2)+[(j-c2)*(d1-c1+1)+i-c1)]*L
6
例1〖软考题〗:一个二维数组A[1..6, 0..7],每个数组元素
16
5.4
1、定义:
广义表的定义
广义表是线性表的推广,也称为列表(lists) 记为: LS = ( a1 , a2 , ……, an ) 广义表名 表头(Head) 表尾 (Tail) n是表长
在广义表中约定:
① 第一个元素是表头,而其余元素组成的表称为表尾; ② 用小写字母表示原子类型,用大写字母表示列表。
13
1 Status Value(Array A,ElemType &e,…){ 2 //A是n维数组,e为元素变量,随后是n个下标值,若各下
标不超界,则e赋值为所指定的A的元素值,即将指定元素值 读到e变量中。
数据结构递归与广义表

第5章递归与广义表一、复习要点本章主要讨论递归过程和广义表。
一个递归的定义可以用递归的过程计算,一个递归的数据结构可以用递归的过程实现它的各种操作,一个递归问题也可以用递归的过程求解。
因此,递归算法的设计是必须掌握的基本功。
递归算法的一般形式:void p ( 参数表) {if( 递归结束条件)可直接求解步骤;基本项else p( 较小的参数);归纳项}在设计递归算法时,可以先考虑在什么条件下可以直接求解。
如果可以直接求解,考虑求解的步骤,设计基本项;如果不能直接求解,考虑是否可以把问题规模缩小求解,设计归纳项,从而给出递归求解的算法。
必须通过多个递归过程的事例,理解递归。
但需要说明的是,递归过程在时间方面是低效的。
广义表是一种表,它的特点是允许表中套表。
因此,它不一定是线性结构。
它可以是复杂的非线性结构,甚至允许递归。
可以用多重链表定义广义表。
在讨论广义表时,特别注意递归在广义表操作实现中的应用。
本章复习的要点:1、基本知识点要求理解递归的概念:什么是递归?递归的定义、递归的数据结构、递归问题以及递归问题的递归求解方法。
理解递归过程的机制与利用递归工作栈实现递归的方法。
通过迷宫问题,理解递归解法,从而掌握利用栈如何实现递归问题的非递归解法。
在广义表方面,要求理解广义表的概念,广义表的几个性质,用图表示广义表的方法,广义表操作的使用,广义表存储结构的实现,广义表的访问算法,以及广义表的递归算法。
2、算法设计求解汉诺塔问题,掌握分治法的解题思路。
求解迷宫问题、八皇后问题,掌握回溯法的解题思路。
对比单链表的递归解法和非递归解法,掌握单向递归问题的迭代解法。
计算广义表结点个数,广义表深度,广义表长度的递归算法。
输出广义表各个原子所在深度的非递归算法。
判断两个广义表相等的递归算法。
广义表的按深度方向遍历和按层次(广度)方向遍历的递归算法。
使用栈的广义表的按深度方向遍历的非递归算法。
递归的广义表的删除算法二、难点与重点1、递归:递归的定义、递归的数据结构、递归问题用递归过程求解链表是递归的数据结构,可用递归过程求解有关链表的问题2、递归实现时栈的应用递归的分层(树形)表示:递归树递归深度(递归树的深度)与递归工作栈的关系单向递归与尾递归的迭代实现3、广义表:广义表定义、长度、深度、表头、表尾用图形表示广义表的存储结构广义表的递归算法,包括复制、求深度、求长度、删除等算法三、教材中习题的解析5-1 已知A[n]为整数数组,试写出实现下列运算的递归算法:(1) 求数组A中的最大整数。
《数据结构》习题集:第5章

第5章数组与广义表一、选择题1.在以下讲述中,正确的是(B )。
A、线性表的线性存储结构优于链表存储结构B、二维数组是其数据元素为线性表的线性表C、栈的操作方式是先进先出D、队列的操作方式是先进后出2.若采用三元组压缩技术存储稀疏矩阵,只要把每个元素的行下标和列下标互换,就完成了对该矩阵的转置运算,这种观点(A )。
A、正确B、错误3.二维数组SA 中,每个元素的长度为3 个字节,行下标I 从0 到7,列下标J 从0 到9,从首地址SA 开始连续存放在存储器内,该数组按列存放时,元素A[4][7]的起始地址为(B)。
A、SA+141B、SA+180C、SA+222D、SA+2254.数组SA 中,每个元素的长度为3 个字节,行下标I 从0 到7,列下标J 从0 到9,从首地址SA 开始连续存放在存储器内,存放该数组至少需要的字节数是( C )。
A、80B、100C、240D、2705.常对数组进行的两种基本操作是(B )。
A、建立与删除B、索引和修改C、查找和修改D、查找和索引6.将一个A[15][15]的下三角矩阵(第一个元素为A[0][0]),按行优先存入一维数组B[120]中,A 中元素A[6][5]在B 数组中的位置K 为( B )。
A、19B、26C、21D、157.若广义表A 满足Head(A)=Tail(A),则A 为(B )。
A、()B、(())C、((),())D、((),(),())8.广义表((a),a)的表头是( C ),表尾是(C )。
A、aB、bC、(a)D、((a))9.广义表((a,b),c,d)的表头是( C ),表尾是(D )。
A、aB、bC、(a,b)D、(c,d)10.广义表((a))的表头是( B ),表尾是(C )。
A、aB、(a)C、()D、((a))11.广义表(a,b,c,d)的表头是(A ),表尾是(D )。
A、aB、(a)C、(a,b)D、(b,c,d)12.广义表((a,b,c,d))的表头是(C ),表尾是(B )。
《数据结构与算法》第五章-数组和广义表学习指导材料

《数据结构与算法》第五章数组和广义表本章介绍的数组与广义表可视为线性表的推广,其特点是数据元素仍然是一个表。
本章讨论多维数组的逻辑结构和存储结构、特殊矩阵、矩阵的压缩存储、广义表的逻辑结构和存储结构等。
5.1 多维数组5.1.1 数组的逻辑结构数组是我们很熟悉的一种数据结构,它可以看作线性表的推广。
数组作为一种数据结构其特点是结构中的元素本身可以是具有某种结构的数据,但属于同一数据类型,比如:一维数组可以看作一个线性表,二维数组可以看作“数据元素是一维数组”的一维数组,三维数组可以看作“数据元素是二维数组”的一维数组,依此类推。
图5.1是一个m行n列的二维数组。
5.1.2 数组的内存映象现在来讨论数组在计算机中的存储表示。
通常,数组在内存被映象为向量,即用向量作为数组的一种存储结构,这是因为内存的地址空间是一维的,数组的行列固定后,通过一个映象函数,则可根据数组元素的下标得到它的存储地址。
对于一维数组按下标顺序分配即可。
对多维数组分配时,要把它的元素映象存储在一维存储器中,一般有两种存储方式:一是以行为主序(或先行后列)的顺序存放,如BASIC、PASCAL、COBOL、C等程序设计语言中用的是以行为主的顺序分配,即一行分配完了接着分配下一行。
另一种是以列为主序(先列后行)的顺序存放,如FORTRAN语言中,用的是以列为主序的分配顺序,即一列一列地分配。
以行为主序的分配规律是:最右边的下标先变化,即最右下标从小到大,循环一遍后,右边第二个下标再变,…,从右向左,最后是左下标。
以列为主序分配的规律恰好相反:最左边的下标先变化,即最左下标从小到大,循环一遍后,左边第二个下标再变,…,从左向右,最后是右下标。
例如一个2×3二维数组,逻辑结构可以用图5.2表示。
以行为主序的内存映象如图5.3(a)所示。
分配顺序为:a11 ,a12 ,a13 ,a21 ,a22,a23 ; 以列为主序的分配顺序为:a11 ,a21 ,a12 ,a22,a13 ,a23 ; 它的内存映象如图5.3(b)所示。
《数据结构(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 子表
数据结构第五章

5.3.1 特殊矩阵
是指非零元素或零元素的分布有一定规律的矩阵。
1、对称矩阵 在一个n阶方阵A中,若元素满足下述性质: aij = aji 0≦i,j≦n-1 则称A为对称矩阵。
对称矩阵中的元素关于主对角线对称,故只 要存储矩阵中上三角或下三角中的元素,这样, 能节约近一半的存储空间。
2013-7-25 第4章 18
5.3 矩阵的压缩存储
在科学与工程计算问题中,矩阵是一种常用 的数学对象,在高级语言编制程序时,常将 一个矩阵描述为一个二维数组。 当矩阵中的非零元素呈某种规律分布或者矩 阵中出现大量的零元素的情况下,会占用许 多单元去存储重复的非零元素或零元素,这 对高阶矩阵会造成极大的浪费。 为了节省存储空间,我们可以对这类矩阵进 行压缩存储:
5.2 数组的顺序表示和实现 由于计算机的内存结构是一维的, 因此用一维内存来表示多维数组,就必 须按某种次序将数组元素排成一列序列 ,然后将这个线性序列存放在存储器中 。 又由于对数组一般不做插入和删除 操作,也就是说,数组一旦建立,结构 中的元素个数和元素间的关系就不再发 生变化。因此,一般都是采用顺序存储 的方法来表示数组。
即为多个相同的非零元素只分配一个存储空间; 对零元素不分配空间。
课堂讨论: 1. 什么是压缩存储? 若多个数据元素的值都相同,则只分配一个元素值的 存储空间,且零元素不占存储空间。 2. 所有二维数组(矩阵)都能压缩吗? 未必,要看矩阵是否具备以上压缩条件。 3. 什么样的矩阵具备以上压缩条件? 一些特殊矩阵,如:对称矩阵,对角矩阵,三角矩阵, 稀疏矩阵等。 4. 什么叫稀疏矩阵? 矩阵中非零元素的个数较少(一般小于5%)
通常有两种顺序存储方式:
⑴行优先顺序——将数组元素按行排列,第i+1个行 向量紧接在第i个行向量后面。以二维数组为例,按 行优先顺序存储的线性序列为: a11,a12,…,a1n,a21,a22,…a2n,……,am1,am2,…,amn 在PASCAL、C语言中,数组就是按行优先顺序存 储的。 ⑵列优先顺序——将数组元素按列向量排列,第j+1 个列向量紧接在第j个列向量之后,A的m*n个元素按 列优先顺序存储的线性序列为: a11,a21,…,am1,a12,a22,…am2,……,an1,an2,…,anm 在FORTRAN语言中,数组就是按列优先顺序存储的。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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; }
何谓"递归函数 ? 何谓 递归函数"? 递归函数
一个含直接或间接调用本函数语句的函数被 称之为递归函数,它必须满足以下两个条件: 称之为递归函数,它必须满足以下两个条件: 在每一次调用自己时,必须是(在某种意义 ①在每一次调用自己时,必须是 在某种意义 更接近于解; 上)更接近于解; 更接近于解 函数中必须有一个终止处理或计算的准则。 ②函数中必须有一个终止处理或计算的准则。
的存储结构。 例:广义表 L=(a,(x,y),((z))) 的存储结构。
可由对L进行表头和表尾的分析得到 若列表不空 可由对 进行表头和表尾的分析得到--若列表不空, 进行表头和表尾的分析得到 若列表不空, 则可分解成表头和表尾(采用头尾链表存储结构)。 则可分解成表头和表尾(采用头尾链表存储结构)。 分析: 分析: ①L为一非空列表 为一非空列表
// 将非空串 分割成两部分: 将非空串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); //从第 个位置起,取1个字符 从第i个位置起 从第 个位置起, 个字符 if(ch=="(") ++k; else if(ch==")") --k; }
⑷ 建立广义表 以广义表字符串S建立广义表 建立广义表。 以广义表字符串 建立广义表。 从前面的讨论可知, 从前面的讨论可知,非空广义表可分解成表头和表 尾两个部分。建表时,可分别建立( 尾两个部分。建表时,可分别建立(分解为两个子 问题): 问题): 表头有两种情况,为单原子或为列表, 两种情况 表头有两种情况,为单原子或为列表,当为列表时 与原问题相同; 与原问题相同; 表尾必为列表,与原问题相同。 必为列表 表尾必为列表,与原问题相同。 函数的功能 设string sever(string& S )函数的功能为: 函数的功能为 从广义表字符串S中提取表头串返回 并将S置成表 中提取表头串返回, 从广义表字符串 中提取表头串返回,并将 置成表 尾串。 尾串。
并且为了在存储结构中便于分辩原子和子表, 并且为了在存储结构中便于分辩原子和子表,令表 示广义表的链表中的结点为"异构 结点,如图所示, 异构"结点 示广义表的链表中的结点为 异构 结点,如图所示, 结点中设有一个"标志域 标志域tag", 并约定 tag=0 表示 结点中设有一个 标志域 , 原子结点, 表示表结点。 原子结点,tag=1 表示表结点。原子结点中的 data 域存储原子, 域存储原子,表结点中指针域的两个值分别指向表 头和表尾。 头和表尾。
5.2.2 广义表的头尾链表存储表示
glist.h #include <iostream> #include <string> using namespace std; enum ElemTag {ATOM,LIST}; typedef char AtomType;
struct GLNode{ ElemTag tag; union { //匿名共用体 匿名共用体 AtomType atom; struct { GLNode *hp,*tp; } ptr; }; }; typedef GLNode* GList;
为广义表的第i个元素 广义表LS可表示为 个元素, 可表示为: 设ai为广义表的第 个元素,广义表 可表示为: LS=(a1,a2,…, an) ( , 其中: 其中: 广义表的名字; ①LS——广义表的名字; 广义表的名字 广义表的长度; ②n——广义表的长度; 广义表的长度 或者是单元素 (小写) ③ ai--表中的元素 ; 或者是表元素 (大写) 空表; ④n=0 空表; 当广义表非空时, 表头( ),其余元素组 ⑤当广义表非空时,称a1为表头(head),其余元素组 ), 成的表( 表尾( ); 成的表(a2,a3, …, an)为表尾(tail); , 广义表的抽象数据类型: 广义表的抽象数据类型:P107
⑶ 求广义表的深度 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 }
5.1.2 举例
分别用圆圈和方框表示表(表元素) 分别用圆圈和方框表示表(表元素)和单元素 ①A=() () 空表,其长度为零。 空表,其长度为零。
②B=(e) ( ) B中只有一个单元素,长度为 ,表头为 ,表尾为 中只有一个单元素, 中只有一个单元素 长度为1,表头为'e', 空。
,(b, , )) ③C=(a,( ,c,d)) ( ,( 长度为2,表头为‘ ,表尾为子表(( ((b, , 长度为 ,表头为‘a’,表尾为子表(( ,c, d))。 ))。
的表头为原子a ②L的表头为原子 的表头为原子
的表尾为列表((x,y),((z))) ③L的表尾为列表 的表尾为列表
的表头为列表(x,y) ④((x,y),((z)))的表头为列表 的表头为列表
其余分析同上。 其余分析同上。
5.2 广义表操作的实现
基于广义表是递归定义的结构, 基于广义表是递归定义的结构,因此实现广 义表操作的算法均为递归函数。 义表操作的算法均为递归函数。
5.1.3广义表的几个性质 广义表的几个性质
①有次序性: 有次序性: 广义表中的数据元素有固定的相对次序。 广义表中的数据元素有固定的相对次序。 线性排列 --线性表的推广 线性表的推广 层次结构 --树的推广 树的推广 有长度: ②有长度: 广义表的长度定义为最外层 最外层括弧中包含的数 广义表的长度定义为最外层括弧中包含的数 据元素个数。 据元素个数。 表元素个数一定,不能无限,可以是空表。 表元素个数一定,不能无限,可以是空表。
第5章 广义表 章
5.1 广义表的定义 5.2 广义表操作的实现
5.1 广义表的定义
5.1.1 定义
广义表( 广义表(Lists)简称表,它是线性表的推广。 )简称表,它是线性表的推广。 一个广义表是n( 一个广义表是 (n≥0)个元素的序列,当 )个元素的序列, n=0时称为空表。在一个非空的广义表中,其 时称为空表。 时称为空表 在一个非空的广义表中, 元素可以是某一确定类型的对象( 元素可以是某一确定类型的对象(这种元素 被称作单元素),也可以是由单元素构成的 单元素), 被称作单元素),也可以是由单元素构成的 这种元素可相对地被称作子表 子表或 表(这种元素可相对地被称作子表或表元 )。显然 广义表的定义是递归的, 显然, 素)。显然,广义表的定义是递归的,广义 表是一种递归的数据结构。 表是一种递归的数据结构。
5.1.4 广义表的存储结构
由于广义表中的数据元素可以是原子, 由于广义表中的数据元素可以是原子,也可 以是广义表,显然难以用顺序存储结构表示。 以是广义表,显然难以用顺序存储结构表示。 由于列表中的数据元素可能为原子或列表, 由于列表中的数据元素可能为原子或列表, 由此需要两种结构的结点:一种是表结点, 由此需要两种结构的结点:一种是表结点, 用以表示列表;一种是原子结点, 用以表示列表;一种是原子结点,用以表示 原子。 原子。
④D=(A,B,C) ( , , ) 长度为3,表头为A, 表尾为( , )。 长度为 ,表头为 表尾为(B,C)。
⑤E=(a,E) ( , ) 长度为2,表头为a,表尾为( ) 表头为 表头为E, 长度为 ,表头为 ,表尾为(E)--表头为 ,表尾为 ()。E相当于无穷表 相当于无穷表( ,( ,(a,( ,( ,(…))))。 ()。 相当于无穷表(a,( (a,( ))))。
void initGList(GList& L); // 创建空的广义表 创建空的广义表L int getLength(GList L); int getDepth(GList L); void creatGList(GList& L,string s); void printGList(GList& L,int k=0);
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; }; }; typedef GLNode* GList;