《数据结构》教案 第四章 数组和广义表
- 格式:doc
- 大小:136.50 KB
- 文档页数:4
第4章数组和广义表【例4-1】二维数组A的每一个元素是由6个字符组成的串,其行下标i=0,1,…,8,列下标j=1,2,…,10。
若A以行为主序存储元素,A[8][5]的物理地址与当A按列为主序存储时的元素()的物理地址相同。
设每个字符占一个字节。
A.A[8][5] B.A[3][10] C.A[5][8] D.A[0][9]解:二维数A是一个9行10列的矩阵,即A[9][10]。
按行存储时,A[8][5]是第85个元素存储的元素。
而按列存储时,第85个存储的元素是A[3][10]。
即正确答案为B。
【例4-2】若对n阶对称矩阵A以行序为主序方式将其下三角形的元素(包括主对角线上所有元素)依次存放于一维数组B[n(n+1)/2]中,则在B中确定的位置k的关系为()。
A.jii+-2)1(*B.ijj+-2)1(*C.jii++2)1(*D.ijj++2)1(*解:如果a ij按行存储,那么它的前面有i-1行,其有元素个数为:1+2+3+…+(i-1)=i(i-1)/2。
同时它又是所在行的第j列,因此它排列的顺序还得加上j,一维数组B[n(n+1)/2]中的位置k与其下标的关系是:jii+-2)1(*。
因此答案为A。
【例4-3】已知n阶下三角矩阵A,按照压缩存储的思想,可以将其主对角线以下所有元素(包括主对角线上元素)依次存放于一维数组B中。
请写出从第一列开始以列序为主序分配方式时在B中确定元素a ij的存放位置的公式。
解:如果a ij按列存储,那么它的前面有j-1列,共有元素:n+(n-1)+(n-2)+ …+[n-(j-2)]=(j-1)*n-2)1)(2(--jj而它又是所在列的第i行,因此在它前的元素个数还得加上i。
因此它在一维数组B中的存储顺序为:(j-1)*n-2)1)(2(--jj+i【例4-4】已知广义表L=((x,y,z),a,(u,t,w)),从L表中取出的原子项ASCII码最大的运算是()。
目录3.1串类型定义 (2)3.2串的表示与实现 (4)3.2.1 定长顺序存储表示 (4)3.2.2 堆分配存储表示 (4)3.2.3 串的块链存储表示 (5)3.3串操作应用举例 (5)3.3.1 文本编辑 (5)3.3.2 建立词索引表 (5)4.1数组的定义 (5)4.2数组的顺序表示和实现 (6)4.3矩阵的压缩存储 (7)4.3.1 特殊矩阵 (7)4.3.2 稀疏矩阵 (7)第3章串3.1 串类型定义1、串与一般线性表的关系串是特殊的线性表,这种特殊性表现在:·串的元素是字符型·串的操作不仅仅是针对元素个体,还包括整体的操作,如串的复制、联接等。
2、一些概念串:由零个或多个字符组成的有限序列;串的长度:串中字符的数目;空串:零个字符的串;子串:串中任意个连续字符组成的子序列;主串:包含子串的串;字符在串中的位置:字符在序列中的序号;子串在主串中的位置:子串的第一个字符在主串中的位置;两个串的相等:两个串的值相等,即串长相等,且各对应位置的字符都相等;3、串值的表示用一对单引号括起来(一些程序设计语言用双引号将传串值括起来)。
空格串与空串的区别:空格串是指由一个或多个空格组成的串;空串是指包含零个字符的串。
4、串的抽象数据类型定义ADT String{数据对象:D={a i|a i∈CharacterSet, i=1,2,…,n, n≥0}数据关系:R={R1},R1={<a i-1,a i>|a i-1,a i∈D, i=2,3,…,n }基本操作:StrAssign(&T, chars)初始条件:chars是字符串常量操作结果:生成一个其值等于chars的串TStrCopy(&T, S)初始条件:串S存在操作结果:由串S复制得串TStrEmpty(S)初始条件:串S存在操作结果:若S为空串,则返回TRUE,否则返回FALSEStrCompare(S, T)初始条件:串S和T存在操作结果:若串S>T,则返回值>0;若串S=T,则返回值=0;若串S<T,则返回值<0StrLength(S)初始条件:串S已存在操作结果:返回串S中数据元素的个数ClearString(&S)初始条件:串S已存在操作结果:将串S清为空串Concat(&T, S1, S2)初始条件:串S1和S2存在操作结果:用T返回由S1和S2联接而成的新串SubString(&Sub, S, pos, len)初始条件:串S存在,1 ≤ pos ≤ StrLength(S)且0 ≤ len ≤ StrLength(S)-pos+1操作结果:用Sub返回串S的第pos个字符起长度为len的子串Index(S, T, pos)初始条件:串S和T存在,T非空,1 ≤ pos ≤ StrLength(S)操作结果:若主串S中存在和串T值相同的子串,则返回它在主串S中第pos个字符之后第一次出现的位置;否则函数值为0 Replace(&S, T, V)初始条件:串S,T和V存在,T是非空串操作结果:用V替换主串S中出现的所有与T相等的不重叠的子串StrInsert(&S, pos, T)初始条件:串S和T存在,1 ≤ pos ≤ StrLength(S)+1操作结果:在串S的第pos个字符之前插入串TStrDelete(&S, pos, len)初始条件:串S存在,1 ≤ pos ≤ StrLength(S)-len+1操作结果:从串S中删除第pos个字符起长度为len的子串DestroyString(&S))初始条件:串S存在操作结果:串S被销毁}ADT String5、串的基本操作1)赋值操作StrAssign(&T, chars)2)比较函数StrCompare(T, S)3)求串长函数StrLength(S)4)联接函数Concat(&T, S1, S2)5)求子串函数SubString(&Sub, S, pos, len)其他操作可在此最小操作集上实现。
数据结构05数组与广义表数组与广义表可以看做是线性表地扩展,即数组与广义表地数据元素本身也是一种数据结构。
5.1 数组地基本概念5.2 数组地存储结构5.3 矩阵地压缩存储5.4 广义表地基本概念数组是由相同类型地一组数据元素组成地一个有限序列。
其数据元素通常也称为数组元素。
数组地每个数据元素都有一个序号,称为下标。
可以通过数组下标访问数据元素。
数据元素受n(n≥1)个线性关系地约束,每个数据元素在n个线性关系地序号 i1,i2,…,in称为该数据元素地下标,并称该数组为n维数组。
如下图是一个m行,n列地二维数组A矩阵任何一个元素都有两个下标,一个为行号,另一个为列号。
如aij表示第i行j列地数据元素。
数组也是一种线性数据结构,它可以看成是线性表地一种扩充。
一维数组可以看作是一个线性表,二维数组可以看作数据元素是一维数组(或线性表)地线性表,其一行或一列就是一个一维数组地数据元素。
如上例地二维数组既可表示成一个行向量地线性表: A1=(a11,a12,···,a1n)A2=(a21,a22, ···,a2n)A=(A1,A2, ···,Am) ············Am=(am1,am2, ···,amn)也可表示成一个列向量地线性表:B1=(a11,a21,···,am1)B2=(a12,a22, ···,am2)A=(B1,B2, ···,Bm) ············Bn=(a1n,a2n, ···,amn)数组地每个数据元素都与一组唯一地下标值对应。
数组与⼴义表5.1数组是由具有某种结构的数据元素构成,⼴义表则是由单个元素或⼦表构成的。
因此数组和⼴义表中的数据元素可以是单个元素,也可以是⼀个具有线性结构的数据。
从这个意义上讲,数组和⼴义表是线性表的推⼴。
“N维数组是数据元素为N-1维数组的线性表”5.2.数组的顺序存储与实现:(1)按⾏序存储(2)按列序存储5.3特殊矩阵的压缩存储特殊矩阵:指具有许多相同矩阵元素或零元素,并且这些相同矩阵元素或零元素的分布有⼀定规律性的矩阵。
常见的特殊矩阵:对称矩阵、上(下)三⾓矩阵、对⾓矩阵三对⾓矩阵:第⼀⾏和最后⼀⾏只有两个元素,其它都是三个元素;第⼀列和最后⼀列都是两个元素,其它列都是三个元素。
特殊矩阵的压缩原则:(1)元素分布有特殊规律的矩阵,寻找规律对应的公式,实现压缩存储。
(2)⾮零元素很少的稀疏矩阵,可采⽤只存储⾮零元素的⽅法实现压缩存储。
稀疏矩阵:是指矩阵中⼤多数元素为零的矩阵压缩存储策略:(1)由于稀疏矩阵中⾮零元素的分布通常没有规律,因此,在存储⾮零元素值的同时,还必须存储该⾮零元素在矩阵中所处的⾏号和列号,相应的⾏和列与⾮零元素构成⼀个三元组(⾏标,列标,值),这就是稀疏矩阵的三元组表⽰法,稀疏矩阵压缩存储后便失去了随机存取性。
优点:节约了空间,使得矩阵中某些运算的时间效率优于经典算法。
(2)为了避免⼤量移动元素,稀疏矩阵也可采⽤链式存储法---⼗字链表,它能够灵活地插⼊因运算⽽产⽣的新的⾮零元素,删除因运算⽽产⽣的新的零元素,实现矩阵的各种运算。
5.4:⼴义表的数据元素可以是单个元素,也可以是⼴义表。
⼴义表的定义是递归定义的(1)⼴义表的元素可以是⼦表,⽽⼦表还可以是⼦表,因此,⼴义表就是⼀个多层的结构。
如A=(a,(b,c))(2)⼴义表可以被其他⼴义表共享,如:B=(A,A,D)通过该⼦表的名称就可以引⽤该表(3)⼴义表具有递归性,如C=(a,C);。
02331数据结构-04数组和广义表1.多维数组和广义表是一种复杂的非线性结构,它们的逻辑特征是:一个数据元素可能有多个直接前驱和多个直接后继。
2.一维数组(向量)是存储于计算机的连续存储空间中的多个具有统一类型的数据元素。
同一数组的不同元素通过不同的下标标识。
(a1,a2,…,an)3.二维数组Amn可视为由m个行向量组成的向量,或由n个列向量组成的向量。
二维数组中的每个元素aij既属于第i行的行向量,又属于第j列的列向量。
4.多维数组:三维数组Amnp可视为以二维数组为数据元素的向量。
四维数组可视为以三维数组为数据元素的向量……三维数组中的每个元素aijk都属于三个向量。
四维数组中的每个元素都属于四个向量……5.数组的顺序存储方式:由于计算机内存是一维的,多维数组的元素应排成线性序列后存人存储器。
数组一般不做插入和删除操作,即结构中元素个数和元素间关系不变化。
一般采用顺序存储方法表示数组。
(1)行优先顺序:将数组元素按行向量排列,第i+1个行向量紧接在第i个行向量后面。
【例】二维数组Amn的按行优先存储的线性序列为:a11,a12,…,a1n,a21,a22,…,a2n,……,am1,am2,…,amn(2)列优先顺序将数组元素按列向量排列,第i+1个列向量紧接在第i个列向量后面。
【例】二维数组Amn的按列优先存储的线性序列为:a11,a21,…,am1,a12,a22,…,am2,……,a1n,a2n,…,amn6.数组元素的地址计算公式:(1)按行优先顺序存储的二维数组Amn地址计算公式LOC(aij)=LOC(a11)+[(i-1)某n+j-1]某d(注:此公式下界为1,如下界为0,则公式变为[i某n+j])①LOC(a11)是开始结点的存放地址(即基地址)②d为每个元素所占的存储单元数③由地址计算公式可得,数组中任一元素可通过地址公式在相同时间内存取。
即顺序存储的数组是随机存取结构。
ch4 数组和广义表
本实习单元是作为从线性结构到非线性结构的过渡来安排的。
数组和广义表可以看成其元素本身也是自身结构( 递归结构 ) 的线性表。
广义表本质上是一种层次结构 , 自顶向下识别并建立一个广义表的操作,可视为某种树的遍历操作:遍历逻辑的〈或符号形式的)结构,访问动作是建立一个结点。
稀疏矩阵的十字链表存储结构也是图的一种存储结构。
由此可见,这个实习单元的训练具有承上启下的作用。
希望读者能深入研究数组的存储表示和实现技术,熟悉广义表的存储结构的特性。
编程技术训练要点:稀疏矩阵的表示方法及其运算的实现(4.1〉;共享数据的存储表示方法(4.2);形式系统的自底向上和自顶向下识别技术(4.3 〉; 递归算法的设计方法(4.3);表达式求值技术 (4.4) 。
1. 稀疏矩阵运算器
【问题描述】
稀疏矩阵是指那些多数元素为零的矩阵。
利用 " 稀疏 " 特点进行存储和计算可以大大节省存储空间 , 提高计算效率。
实现一个能进行稀疏矩阵基本运算的运算器。
【基本要求】
以"带行逻辑链接信息"的三元组顺序表表示稀疏矩阵,实现两个矩阵相加、相减和相乘的运算。
稀疏矩阵的输入形式采用三元组表示 , 而运算结果的矩阵则以通常的阵列形式列出。
【测试数据】
【实现提示】
1. 首先应输入矩阵的行数和列数 , 并判别给出的两个矩阵的行、列数对于所要求作
的运算是否相匹配。
可设矩阵的行数和列数均不超过 20 。
2. 程序可以对三元组的输入顺序加以限制 , 例如 , 按行优先。
注意研究教科书 5.
3.2
节中的算法 , 以便提高计算效率。
3. 在用三元组表示稀疏矩阵时 , 相加或相减所得结果矩阵应该另生成 , 乘积矩阵也可用二维数组存放。
【选作内容】
1. 按教科书 5.3.2 节中的描述方法 , 以十字链表表示稀疏矩阵。
2. 增添矩阵求逆的运算 , 包括不可求逆的情况。
在求逆之前 , 先将稀疏矩阵的内部表示改为十字链表。
2. 多维数组
【问题描述】
设计并模拟实现整型多维数组类型。
【基本要求】
尽管 C 等程序设计语言已经提供了多维数组 , 但在某些情况下 , 定义用户所需的多维数组很有用的。
通过设计并模拟实现多维数组类型 , 可以深刻理解和掌握多维数组。
整型多维数组应具有以下基本功能 :
(1) 定义整型多维数组类型 , 各维的下标是任意整数开始的连续整数 ;
(2) 下标变量赋值 , 执行下标范围检查 ;
(3 〉同类型数组赋值 ;
(4) 子数组赋值 , 例如 ,a[1..n]=a
[2..n+1];a[2..4][3..5]=b[1..3][2..4];
(5) 确定数组的大小。
【测试数据】
由读者指定。
【实现提示】
各基本功能可以分别用函数模拟实现 , 应仔细考虑函数参数的形式和设置。
定义整型多维数组类型时 , 其类型信息可以存储在如下定义的类型的记录中:
#define MaxDim 5
Typedef struct
int dim ,
BoundPtr lower ,
Upper;
ConstPtr constants;
)NArray,*NarrayPtr;
整型多维数组变量的存储结构类型可定义为:
Typedef struct{
ElemType *elem;
Int num;
NArrayType TypeRecord;
}NArrayType;
【选作内容】
(1) 各维的下标是任意字符开始的连续字符。
(2) 数组初始化。
(3) 可修改数组的下标范围。
3. 识别广义表的头或尾
【问题描述】
写一个程序,建立广义表的存储结构,演示在此存储结构上实现的广义表求
头/求尾操作序列的结果。
【基本要求】
(1) 设一个广义表允许分多行输入,其中可以任意地输入空格符,原子是不限长的仅由字母或数字组成的串。
(2) 广义表采用如教科书中图5.8所示结点的存储结构,试按表头和表尾的分解方法编写建立广义表存储结构的算法。
(3) 对已建立存储结构的广义表施行操作,操作序列为一个仅由"t"或"h"组成的串,它可以是空串(此时印出整个广义表),自左至右施行各操作,再以符号形式显示结果。
【测试数据】
【实现提示】
(1) 广义表串可以利用 C 语言中的串类型或者利用实习三中已实现的串类型表示。
(2) 输入广义表时靠括号匹配判断结束,滤掉空格符之后,存于一个串变量中。
(3) 为了实现指定的算法,应在上述广义表串结构上定义以下4个操作:
Test(s):当 S 分别为空串、原子串和其他形式串时,分别返回‘N’,‘E’和‘O’(代表Null,Element和Other)。
hsub(s,h):s 表示一个由逗号隔开的广义表和原子的混合序列,h为变量参数,返回时为表示序列第一项的字符串。
如果s为空串,则h也赋为空串。
tsub(s,t):s的定义同hsub操作;t为变量参数,返回时取从S中除去第一项(及其之后的逗号,如果存在的话)之后的子串。
strip(s,r):s 的定义同 hsub 操作;r为变量参数。
如果串S以"("开头和以")"结束,则返回时取除去这对括号后的子串,否则取空串。
(4) 在广义表的输出形式中,可以适当添加空格符,使得结果更美观。
【选作内容】
(1) 将hsub和tsub这两个操作合为一个(用变量参数h和t分别返回各自的结果),以便提高执行效率。
(2) 设原子为单个字母。
广义表的建立算法改用边读入边建立的自底向上识别策略实现,广义表符号串不整体地缓冲。
4. 简单LISP算术表达式计算器
【问题描述】
设计一个简单的 LISP 算术表达式计算器。
简单 LISP 算术表达式(以下简称表达式)定义如下:
(1) 一个 0..9 的整数;或者
(2)(运算符表达式表达式)
例如,6,(+45),(+(+25)8) 都是表达式,其值分别为6,9和15。
【基本要求】
实现LISP加法表达式的求值。
【测试数据】
6,(+45),(+(+25)8),(+2(+58)),(+(+(+12)(+34))(+(+56)(+78)))
【实现提示】
写一个递归函数:
int Evaluate(FILE * CharFile)
字符文件 CharFile 的每行是一个如上定义的表达式。
每读入CharFile 的一行,求出并返回表达式的值。
可以设计以下辅助函数
status isNumber(char ReadInChar); //视ReadInchar 是否是数字而返回TRUE 或 FALSE 。
int TurnToInteger(char IntChar); // 将字符’0’..’9’转换为整数0..9
【选做内容】
(1) 标准整数类型的 LISP 加法表达式的求值。
(2) 标准整数类型的 LISP 四则运算表达式的求值。
(3) LISP 算术表达式的语法检查。