版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
数组和广义表数组和广义表逻辑上是线性结构的推广数组:元素的结构相同广义表:元素的结构可以不同
1第5章数组和稀疏矩阵5.1数组5.2稀疏矩阵本章小结5.3广义表2数组n(n>1)个相同类型的数据元素构成的有限序列,且该有限序列存储在一块地址连续的内存单元中。类似于采用顺序存储结构的线性表高级语言中的数组intA[10];charB[4][5];5.1.1数组的基本概念3数组的基本概念数组具有以下性质
(1)数组中的数据元素数目固定。一旦定义了一个数组,其数据元素数目不再有增减变化。
(2)数组中的数据元素具有相同的数据类型。
(3)数组中的每个数据元素都和一组唯一的下标值对应。
(4)数组是一种随机存储结构,可随机存取数组中的任意数据元素。4数组的抽象数据类型ADTArray{数据对象:
D={aj1j2……jn|n>0称为数组的维数,ji是数组元素的第i维下标,0≤ji≤bi-1,bi是数组第i维的长度,aj1j2……jn
ElemSet
}数据关系:
R={R1,R2,……Rn}
Ri={<aj1…ji…jn,aj1…ji+1…jn>|0≤jk≤bk-1,1≤k≤n且k≠i,0≤ji≤bi-2,aj1…ji…jn,aj1…ji+1…jn
∈
D,i=2,…,n}基本操作:
Value(A,index1,…,indexn)
操作结果:若各下标不超界,返回数组A的对应下标的元素值
Assign(A,e,index1,…,indexn)
操作结果:若各下标不超界,将变量e的值赋给由n个下标确定的A的元素
ADisp(A,b1,b2,…,bn)
操作结果:输出n维数组A的所有元素值}ADTArray特点:数组一般不做插入和删除操作5一维数组中,一旦a1的存储地址LOC(a1)确定,并假设每个数据元素占用k个存储单元,则任一数据元素ai的存储地址LOC(ai)就可由以下公式求出:
LOC(ai)=LOC(a1)+(i-1)*k(0≤i≤n)可见,一维数组中任一数据元素的存储地址可直接计算得到一维数组中任一数据元素可直接存取,是一种随机存储的结构。5.1.2数组的存储结构6将Am*n简记为AA=(a1,a2,…,ai…,am)其中,ai=(ai,1,ai,2,…,ai,n)二维数组二维数组是一个特殊的一维数组,其每个数据元素都是相同类型的一维数组。任何多维数组都可以看作一个线性表,线性表中的每个数据元素又是一个线性表。多维数组是线性表的推广。7矛盾:计算机的存储结构是线性的、一维的问题:如何用线性的存储结构存放二维数组的元素?解决方法:1)以行序为主序存储:先存储第1行,然后紧接着存储第2行,最后存储第m行2)以列序为主序存储:先存储第1列,然后紧接着存储第2列,最后存储第n列二维数组的存储8数组a[2][3]的顺序存储a0,1a0,0a0,2a1,0a1,1a1,2a0,1a0,0a0,2a1,0a1,1a1,2行序为主序a0,1a0,0a0,2a1,0a1,1a1,2a0,1a0,0a0,2a1,0a1,1a1,2列序为主序9当二维数组Am*n第一个数据元素a1,1的存储地址LOC(a1,1)和每个数据元素所占用的存储单元k确定后,该二维数组中任一数据元素ai,j的存储地址可由下式确定:
LOC(ai,j)=LOC(a1,1)+[(i-1)*n+(j-1)]*k同理可推出在以列序为主序的计算机系统中有:
LOC(ai,j)=LOC(a1,1)+[(j-1)*m+(i-1)]*k
以行序为主序10
例5.1对二维数组floata[5][4]计算:
(1)数组a中的数组元素数目;
(2)若数组a的起始地址为2000,且每个数组元素长度为32位(即4个字节),数组元素a[3][2]的内存地址。
解:该数组的元素数目共有5*4=20个。由于C语言采用行序为主序的存储方式,则有:
LOC(a3,2)=LOC(a0,0)+(i*n+j)*k=2000+(3*4+2)*4=205611特殊矩阵:非零元素或零元素的分布有一定规律特别是在高阶矩阵的情况下,可以利用特殊矩阵的规律,对它们进行压缩存储,以便节省存储空间做法:使多个相同的非零元素共享同一个存储单元,对零元素不分配存储空间5.1.3特殊矩阵的压缩存储12对称矩阵n阶方阵A[n][n]元素满足ai,j=aj,i(0≤i,j≤n-1)对称矩阵中的元素关于主对角线对称,在存储时可只存储对称矩阵中上三角或下三角中的元素,使得对称的元素共享一个存储空间。n2个元素压缩存储到n(n+1)/2个元素的空间中。对称矩阵的压缩存储13
n2个元素←→
n(n+1)/2个元素
A[0..n-1,0..n-1]←→B[0..n(n+1)/2-1]
a[i][j]←→b[k]k=+ji≥j+ii<jk=0123
以行序为主序存储其下三角的元素……a00a10a11a20an-1,0an-1,n-114上三角矩阵:
k=+j–ii≤j时i>j时下三角矩阵:
k=
i≥j时i<j时155.2稀疏矩阵非零元素较少,分布无规律稀疏因子:δ=s/(m*n)<=0.05由于分布无规律,存放非零元素必须同时存放其在矩阵中的位置,即下标和值一起存放一个三元组唯一确定了稀疏矩阵中的一个非零元素存储结构顺序存储结构--三元组顺序表链式存储结构--十字链表165.2.1稀疏矩阵的三元组表示假设有一个6×7阶稀疏矩阵A,A中元素如下图所示,则对应的三元组线性表为:
((0,2,1),(1,1,2),(2,0,3),(3,3,5),(4,4,6),(5,5,7),(5,6,4))若把稀疏矩阵的三元组线性表按顺序存储结构存储,则称为稀疏矩阵的三元组顺序表。17三元组顺序表举例rcd01605-223-831335740-12429rcd04-1210613324932-850-253718三元组顺序表#defineMaxSize<稀疏矩阵中非零元素最多个数>typedef
struct
∥三元组{
int
r,c;∥非零元的行号、列号
ElemTyped;∥非零元的值}TupNode;typedef
struct
{
int
rows,cols;∥矩阵的行数、列数
int
nums;//非零元个数
TupNode
data[MAXSIZE];∥三元组表}TSMatrix;
下面的讨论假设按行有序存储。19
(1)从一个二维矩阵创建其三元组表示以行序方式扫描二维矩阵A,将其非零的元素插入到三元组t的后面。
voidCreatMat(TSMatrix&t,ElemTypeA[M][N]){ inti,j;
t.rows=M;t.cols=N;t.nums=0; for(i=0;i<M;i++) {for(j=0;j<N;j++) if(A[i][j]!=0)/*只存储非零元素*/{t.data[t.nums].r=i;t.data[t.nums].c=j;
t.data[t.nums].d=A[i][j];t.nums++; } }}20(2)三元组元素赋值(插入)int
Value(TSMatrix&t,ElemType
x,int
rs,int
cs)先在三元组t中找到适当的位置k,将t.nums-k个元素后移一位,将指定元素x插入到t.data[k]处。
rcd01605-223-831335740-1242933-521int
Value(TSMatrix&t,ElemType
x,int
rs,int
cs){int
i,k=0;if(rs>=t.rows||cs>=t.cols)return0;
while(k<t.nums&&rs>t.data[k].r)k++; /*查找行*/while(k<t.nums&&rs==t.data[k].r&&cs>t.data[k].c)k++; /*查找列*/if(t.data[k].r==rs&&t.data[k].c==cs)
t.data[k].d=x;/*存在这样的元素
else/*不存在这样的元素时插入一个元素*/{for(i=t.nums-1;i>=k;i--)/*元素后移*/{t.data[i+1].r=t.data[i].r;t.data[i+1].c=t.data[i].c;t.data[i+1].d=t.data[i].d; }
t.data[k].r=rs;t.data[k].c=cs;t.data[k].d=x;
t.nums++;}return1;}22
(3)将指定位置的元素值赋给变量先在三元组t中找到指定的位置,将该处的元素值赋给x。
int
Assign(TSMatrix
t,ElemType&x,int
rs,int
cs){intk=0;if(rs>=t.rows||cs>=t.cols)return0;
while(k<t.nums&&rs>t.data[k].r)k++;while(k<t.nums&&rs==t.data[k].r&&cs>t.data[k].c)k++;if(t.data[k].r==rs&&t.data[k].c==cs){x=t.data[k].d;return1;}elsereturn0;}23
(4)输出三元组
从头到尾扫描三元组t,依次输出元素值。
voidDispMat(TSMatrixt){inti; if(t.nums<=0)return;
printf(“\t%d\t%d\t%d\n",t.rows,t.cols,t.nums);
printf("------------------\n"); for(i=0;i<t.nums;i++)
printf("\t%d\t%d\t%d\n",t.data[i].r,t.data[i].c,t.data[i].d);}24稀疏矩阵非零元素较少,分布无规律稀疏因子:δ=s/(m*n)<=0.05由于分布无规律,存放非零元素必须同时存放其在矩阵中的位置,即下标和值一起存放一个三元组唯一确定了稀疏矩阵中的一个非零元素三元组顺序表:用顺序存储结构组织三元组25
(5)矩阵转置
对于一个m×n的矩阵Am×n,其转置矩阵是一个n×m的矩阵。设为Bn×m,满足ai,j=bj,i,其中1≤i≤m,1≤j≤n。
rcd01605-223-831335740-12429rcd04-1210613324932-850-253726voidTranTat(TSMatrix
t,TSMatrix&tb){int
p,q=0,v; /*q为tb.data的下标*/
tb.rows=t.cols;tb.cols=t.rows;tb.nums=t.nums;if(t.nums!=0){for(v=0;v<t.cols;v++) for(p=0;p<t.nums;p++)/*p为t.data的下标*/
if(t.data[p].c==v){ tb.data[q].r=t.data[p].c;
tb.data[q].c=t.data[p].r;
tb.data[q].d=t.data[p].d;q++;}}}27十字链表为稀疏矩阵的每一行设置一个单独链表,同时也为每一列设置一个单独链表。稀疏矩阵的每一个非零元素同时包含在两个链表中,即每一个非零元素同时包含在所在行的行链表中和所在列的列链表中。这就大大降低了链表的长度,方便了算法中行方向和列方向的搜索,大大降低了算法的时间复杂度。5.2.2稀疏矩阵的十字链表表示28
(a)结点结构(b)头结点结构十字链表中,每个非零元素用一个结点表示,结点结构如下图(a)所示。其中i、j、value分别代表非零元素所在的行号、列号和相应的元素值;down和right分别称为向下指针和向右指针,分别用来链接同列中和同行中的下一个非零元素结点。29行头结点和列头结点的i,j域值均为0;行头结点的right指针指向该行链表的第一个结点,它的down指针为空;列头结点的down指针指向该列链表的第一个结点,它的right指针为空。行头结点和列头结点必须顺序链接,这样当需要逐行(列)搜索时,才能一行(列)搜索完后顺序搜索下一行(列),行头结点和列头结点均用next指针完成顺序链接。3031十字链表结点结构和头结点的数据结构可定义如下:#defineM3 /*矩阵行*/#defineN4 /*矩阵列*/#defineMax((M)>(N)?(M):(N))/*矩阵行列较大者*/typedef
struct
mtxn
{introw; /*行号*/
int
col; /*列号*/
struct
mtxn*right,*down; /*向右和向下的指针*/union{intvalue;
struct
mtxn*next;}tag;}MatNode; /*十字链表类型定义*/325.3.1广义表的定义广义表简称表,它是线性表的推广。一个广义表是n(n≥0)个元素的一个序列,若n=0时则称为空表。设ai为广义表的第i个元素,则广义表GL的一般表示与线性表相同:
GL=(a1,a2,…,ai,…,an)其中n表示广义表的长度,即广义表中所含元素的个数,n≥0。如果ai是单个数据元素,则ai是广义表GL的原子;如果ai是一个广义表,则ai是广义表GL的子表。5.3广义表33
(1)广义表中的数据元素有相对次序;
(2)广义表的长度定义为最外层包含元素个数;
(3)广义表的深度定义为所含括弧的重数。其中,原子的深度为0,空表的深度为1;
(4)广义表可以共享;一个广义表可以为其他广义表共享;这种共享广义表称为再入表;
(5)广义表可以是一个递归的表。一个广义表可以是自已的子表。这种广义表称为递归表。递归表的深度是无穷值,长度是有限值;
(6)任何一个非空广义表GL均可分解为表头head(GL)=a1和表尾tail(GL)=(a2,…,an)
两部分。广义表的特性34我们规定用小写字母表示原子,用大写字母表示广义表的表名。例如:
A=()B=(e)C=(a,(b,c,d))D=(A,B,C)=((),(e),(a,(b,c,d)))E=((a,(a,b),((a,b),c)))分别求出上述各表的表头、表尾、深度和长度。长度:最外层包含元素个数深度:所含括弧的重数35广义表是一种递归的数据结构,因此很难为每个广义表分配固定大小的存储空间,所以其存储结构只好采用动态链式结构。5.3.2广义表的存储结构(略)36广义表的两种基本情况为原子的情况
:37(1)求广义表的长度在广义表中,同一层次的每个结点是通过link域链接起来的,所以可把它看做是由link域链接起来的单链表。这样,求广义表的长度就是求单链表的长度。求广义表长度的非递归算法如下:
int
GLLength(GLNode*g)//g为一个广义表头结点的指针
{intn=0;g=g->val.sublist;//g指向广义表的第一个元素
while(g!=NULL){n++;g=g->link;}returnn;}5.3.3广义表的运算(略)38对于带头结点的广义表g,广义表深度的递归定义是它等于所有子表中表的最大深度加1。若g为原子,其深度为0。求广义表深度的递归模型f()如下:f(g)=0若g为原子
1 若g为空表MAX{f(subg)}+1其他情况,subg为g的子表
(2)求广义表的深度39int
GLDepth(GLNode*g)//求带头结点的广义表g的深度{intmax=0,dep;if(g->tag==0)return0; //为原子时返回0g=g->val.sublist; //g指向第一个元素
if(g==NULL)return1;//为空表时返回1while(g!=NULL) //遍历表中
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 肠内营养护理书写
- 2025版卒中常见症状及护理管理
- 护理的新技术新疗法汇报
- 支气管炎常见症状及护理手册
- 偏瘫患者上肢肌力训练
- 本溪市教师招聘面试题及答案
- 胰腺炎常见症状及护理要领
- 2026 专注力与生活习惯课件
- 2026 儿童适应能力陌生环境探索课件
- 职业健康安全管理体系培训
- 2025 SMETA确保员工合法工作权的核查程序-SEDEX验厂专用文件(可编辑)
- 雨水改造工程施工合同
- 2025年北京八中学团课考试题及答案
- 职业指导师课件材料
- 学堂在线研究生素养课-积极心理与情绪智慧期末考试答案
- GB/T 45451.2-2025包装塑料桶第2部分:公称容量为208.2 L至220 L的不可拆盖(闭口)桶
- 环卫工人安全培训
- 食品生产企业有害生物风险管理指南
- 高温防汛安全专项施工方案
- 工程热力学教案1(05版)
- 全国各气象台站区站号及经纬度
评论
0/150
提交评论