第五章 数组和广义表.ppt
《第五章 数组和广义表.ppt》由会员分享,可在线阅读,更多相关《第五章 数组和广义表.ppt(120页珍藏版)》请在三一办公上搜索。
1、1,第五章 数组和广义表,2,作为抽象数据类型的数组,一维数组一维数组的示例,5.1数组的定义,3,一维数组的特点,连续存储的线性聚集(别名 向量)除第一个元素外,其他每一个元素有一个且仅有一个直接前驱。除最后一个元素外,其他每一个元素有一个且仅有一个直接后继。,4,数组的定义和初始化,#include class szcl int e;public:szcl()e=0;szcl(int value)e=value;int get_value()return e;,5,main()szcl a13=3,5,7,*elem;for(int i=0,i3,i+)cout a1i.get_value
2、()“n”;/打印静态数组 elem=,6,一维数组(Array)类的定义,#include#include template class Array Type*elements;/数组存放空间 int ArraySize;/当前长度 void getArray();/建立数组空间 public:Array(int Size=DefaultSize);Array(const Array,7,Array()delete elements;Array,8,template void Array:getArray()/私有函数:创建数组存储空间 elements=new TypeArraySize;
3、if(elements=0)cerr Memory Allocation Error endl;,一维数组公共操作的实现,9,template void Array:Array(int sz)/构造函数 if(sz=0)cerr Invalid Array Size endl;return;ArraySize=sz;getArray();,10,template Array:Array(const Array,11,template Type,12,template void Array:Resize(int sz)if(sz=0,13,行向量 下标 i 页向量 下标 i列向量 下标 j 行向
4、量 下标 j 列向量 下标 k,二维数组 三维数组,14,数组的ADT定义,ADT Array 数据对象:ji=0,bi-1,i=1,2,n D=aj1j2jn|n称为数组的维数,bi是数组第i维的长度,ji是数组元素的第i维下标,aj1j2jn ElemSet R=R1,R2,Rn/每个元素受到n个关系的约束 Ri=|0 jk bk-1,1 k n 且 k i 0 ji bi-2,aj1jijn,aj1,ji+1jn D,i=2,n P:InitArray(&A,n,bound1,boundn)DestoryArray(&A)Value(A,&e,index1,indexn)/取出元素值 A
5、ssign(&A,e,index1,indexn)/给元素赋值ADT Array,15,5.2数组的顺序表示和实现,一维数组,LOC(i)=LOC(i-1)+l=+i*l,16,行优先 LOC(j,k)=a+(j*m+k)*l,二维数组,17,n维数组,各维元素个数为 m1,m2,m3,mn下标为 i1,i2,i3,in 的数组元素的存储地址:,18,1 设二维数组A5,6的每个元素占4个字节,已知Loc(a00)=1000,A共占多少个字节?A的终端结点a45的起始地位为何?按行和按列优先存储时,a25的起始地址分别为何?,因含5*6=30个元素,因此A共占30*4=120个字节。a45的起
6、始地址为:Loc(a45)=Loc(a00)+(i*m1+j)*l=1000+(4*6+5)*4=1116,按行优先顺序排列时,a25=1000+(2*6+5)*4=1068按列优先顺序排列时:(二维数组可用行列下标互换来计算)a25=1000+(5*5+2)*4=1108,19,按行优先的顺序排列时,先变化右边的下标,也就是右到左依次变化,这个四维数组的排列是这样的:(将这个排列分行写出以便阅读,只要按从左到右的顺序存放就是在内存中的排列位置),请按行及按列优先顺序列出四维数组A2*3*2*3的所有元素在内存中的存储次序,开始结点为a0000.,a0000 a0001 a0002 a0010
7、 a0011 a0012 a0100 a0101 a0102 a0110 a0111 a0112 a0200 a0201 a0202 a0210 a0211 a0212 a1000 a1001 a1002 a1010 a1011 a1012 a1100 a1101 a1102 a1110 a1111 a1112 a1200 a1201 a1202 a1210 a1211 a1212,20,数组的顺序存储表示和实现,p93-94,21,22,5.3矩阵的压缩存储,特殊矩阵 值相同的元素或零元素在矩阵中的分布有规律对称矩阵三角矩阵对角矩阵稀疏矩阵 值相同的元素或零元素在矩阵中的分布无规律,且零元素
8、个数/矩阵所有元素个数=0.05,23,5.3.1 特殊矩阵的压缩存储,24,(a)一个下三角矩阵(b)下三角矩阵的压缩存储形式矩阵及用下三角压缩存储,25,26,27,3对角矩阵我们仅讨论三对角矩阵的压缩存储,五对角矩阵,七对角矩阵等读者可以作类似分析。在一个nn的三对角矩阵中,只有n+n-1+n-1个非零元素,故只需3n-2个存储单元即可,零元已不占用存储单元。故可将nn三对角矩阵A压缩存放到只有3n-2个存储单元的s向量中,假设仍按行优先顺序存放,,sk与aij的对应关系为:3i或 3j 当 i=j k=3i+1或3j-2 当i=j-1,3i-1 或3j+2 当 i=j+1,28,特殊矩
9、阵的压缩存储,小结特殊矩阵(如对称矩阵、三角矩阵、对角矩阵等)中,非零元素的分布有明显的规律,因此我们可以将其压缩存储到一维数组中,并找到每个非零元素在一维数组中的对应关系,29,30,5.3.2 稀疏矩阵(Sparse Matrix),行数m=6,列数n=7,非零元素个数t=6稀疏因子=0.05,31,稀疏矩阵(SparseMatrix)的抽象数据类型 template class SparseMatrix int Rows,Cols,Terms;/行/列/非零元素数 Trituple smArrayMaxTerms;public:/三元组表 SparseMatrix(int MaxRow,
10、int Maxcol);SparseMatrix Transpose();/转置 SparseMatrix/相加 Add(SparseMatrix b);SparseMatrix/相乘 Multiply(SparseMatrix b);,32,三元组(Trituple)类的定义 template class SparseMatrix;template class Trituple friend class SparseMatrix private:int row,col;/非零元素所在行号/列号 Type value;/非零元素的值,33,稀疏矩阵,转置矩阵,34,1 用三元组表表示的稀疏矩阵
11、及其转置,35,稀疏矩阵转置算法5.1思想p99A的列序 B的行序,设矩阵列数为Cols,对矩阵三元组表扫描Cols次。第k次检测列号为k的项。第k次扫描找寻所有列号为k的项,将其行号变列号、列号变行号,顺次存于转置矩阵三元组表。设矩阵三元组表总共有Terms项,其时间代价为 O(Cols*Terms)。若矩阵有200行,200列Cols,10,000个非零元素Terms,总共有2,000,000次处理。,一般矩阵转置算法Rows*Cols Terms=Rows*Cols,36,稀疏矩阵的转置 template SparseMatrix SparseMatrix:Transpose()Spar
12、seMatrix b;b.Rows=Cols;b.Cols=Rows;b.Terms=Terms;/转置矩阵的列数,行数和非零元素个数 if(Terms 0)int CurrentB=0;/转置三元组表存放指针,37,for(int k=0;kCols;k+)for(int i=0;iTerms;i+)if(smArrayi.col=k)b.smArrayCurrentB.row=k;b.smArrayCurrentB.col=smArrayi.row;b.smArrayCurrentB.value=smArrayi.value;CurrentB+;return b;,38,快速转置算法5.2
13、 p100,建立辅助数组rowSize和rowStart,记录矩阵转置后各行非零元素个数和各行元素在转置三元组表中开始存放位置。(转置前为列)扫描矩阵三元组表,根据某项的列号,确定它转置后的行号,查rowStart表,按查到的位置直接将该项存入转置三元组表中。转置时间代价为 O(max(Terms,Cols)。若矩阵有200列,10000个非零元素,总共需10000次处理。,39,快速转置算法 例,40,for(int i=0;iCols;i+)rowSizei=0;for(i=0;iTerms;i+)rowSizesmArrayi.col+;/rowStart0=0;for(i=1;i Co
14、ls;i+)rowStarti=rowStarti-1+rowSizei-1;/A的第i列开始存放的位置=A的第i-1列开始存放的位置+A的第i-1列非零个数,41,42,2带行指针的链表把具有相同行号的非零元用一个单链表连接起来,稀疏矩阵中的若干行组成若干个单链表,合起来称为带行指针的链表。例如,图1 的稀疏矩阵M的带行指针的链表描述形式见图2。,图2 带行指针的链表,2带行指针的链表,图1 稀疏矩阵M,43,44,在上节提到的特殊矩阵中,元素的分布呈现某种规律,故一定能找到一种合适的方法,将它们进行压缩存放。但是,在实际应用中,我们还经常会遇到一类矩阵:其矩阵阶数很大,非零元个数较少,零元
15、很多,但非零元的排列没有一定规律,我们称这一类矩阵为稀疏矩阵。按照压缩存储的概念,要存放稀疏矩阵的元素,由于没有某种规律,除存放非零元的值外,还必须存储适当的辅助信息,才能迅速确定一个非零元是矩阵中的哪一个位置上的元素。下面将介绍稀疏矩阵的几种存储方法及一些算法的实现。,5.4 稀疏矩阵,45,5.4.1 稀疏矩阵的存储,1三元组表在压缩存放稀疏矩阵的非零元同时,若还存放此非零元所在的行号和列号,则称为三元组表法,即称稀疏矩阵可用三元组表进行压缩存储,但它是一种顺序存储(按行优先顺序存放)。一个非零元有行号、列号、值,为一个三元组,整个稀疏矩阵中非零元的三元组合起来称为三元组表。此时,数据类型
16、可描述如下:#define maxsize 100/*定义非零元的最大数目*/struct node/*定义一个三元组*/int i,j;/*非零元行、列号*/int v;/*非零元值*/;struct sparmatrix/*定义稀疏矩阵*/int rows,cols;/*稀疏矩阵行、列数*/int terms;/*稀疏矩阵非零元个数*/node data maxsize;/*三元组表*/;,46,47,2带行指针的链表把具有相同行号的非零元用一个单链表连接起来,稀疏矩阵中的若干行组成若干个单链表,合起来称为带行指针的链表。例如,图5-6的稀疏矩阵M的带行指针的链表描述形式见图5-9。,图5
17、-9 带行指针的链表,48,3十字链表当稀疏矩阵中非零元的位置或个数经常变动时,三元组就不适合于作稀疏矩阵的存储结构,此时,采用链表作为存储结构更为恰当。十字链表为稀疏矩阵中的链接存储中的一种较好的存储方法,在该方法中,每一个非零元用一个结点表示,结点中除了表示非零元所在的行、列和值的三元组(i,j,v)外,还需增加两个链域:行指针域(rptr),用来指向本行中下一个非零元素;列指针域(cptr),用来指向本列中下一个非零元素。稀疏矩阵中同一行的非零元通过向右的rptr指针链接成一个带表头结点的循环链表。同一列的非零元也通过cptr指针链接成一个带表头结点的循环链表。因此,每个非零元既是第i行
18、循环链表中的一个结点,又是第j列循环链表中的一个结点,相当于处在一个十字交叉路口,故称链表为十字链表。另外,为了运算方便,我们规定行、列循环链表的表头结点和表示非零元的结点一样,也定为五个域,且规定行、列、域值为0(因此,为了使表头结点和表示非零元的表结点不发生混淆,三元组中,输入行和列的下标不能从0开始!而必须从1开始),并且将所有的行、列链表和头结点一起链成一个循环链表。在行(列)表头结点中,行、列域的值都为0,故两组表头结点可以共用,即第i行链表和第i列链表共用一个表头结点,这些表头结点本身又可以通过V域(非零元值域,但在表头结点中为next,指向下一个表头结点)相链接。另外,再增加一个
19、附加结点(由指针hm指示,行、列域分别为稀疏矩阵的行、列数目),附加结点指向第一个表头结点,则整个十字链表可由hm指针惟一确定。,49,例如,图5-6的稀疏矩阵M的十字链表描述形式见图5-10。十字链表的数据类型描述如下:struct linknode int i,j;struct linknode*cptr,*rptr;union vnext/*定义一个共用体*/int v;/*表结点使用V域,表示非零元值*/struct linknode next;/*表头结点使用next域*/k;,50,图5-10 稀疏矩阵的十字链表,51,5.4.2 稀疏矩阵的运算,1稀疏矩阵的转置运算下面将讨论三元
20、组表上如何实现稀疏矩阵的转置运算。转置是矩阵中最简单的一种运算。对于一个mn的矩阵A,它的转置矩阵B是一个nm 的,且Bij=Aji,0in,0jm。例如,图5-6给出的M矩阵和图5-7给出的N矩阵互为转置矩阵。在三元组表表示的稀疏矩阵中,怎样求得它的转置呢?从转置的性质知道,将A转置为B,就是将A的三元组表a.data变为B的三元组表b.data,这时可以将a.data中i和j的值互换,则得到的b.data是一个按列优先顺序排列的三元组表,再将它的顺序适当调整,变成行优先排列,即得到转置矩阵B。下面将用两种方法处理:(1)按照A的列序进行转置由于A的列即为B的行,在a.data中,按列扫描,
21、则得到的b.data必按行优先存放。但为了找到A的每一列中所有的非零的元素,每次都必须从头到尾扫描A的三元组表(有多少列,则扫描多少遍),这时算法描述如下:,52,#define maxsize 100struct node int i,j;/*定义三元组的行、列号*/int v;/*三元组的值*/;struct sparmatrix int rows,cols;/*稀疏矩阵的行、列数*/int terms;/*稀疏矩阵的非零元个数*/struct node datamaxsize;/*存放稀疏矩阵的三元组表*/;void transpose(struct sparmatrix a)struc
22、t sparmatrix b;/*b为a的转置*/int ano,bno=0,col,i;b.rows=a.cols;b.cols=a.rows;b.terms=a.terms;if(b.terms0)for(col=0;cola.cols;col+)/*按列号扫描*/for(ano=0;anoa.terms;ano+)/*对三元组扫描*/,53,if(a.dataano.j=col)/*进行转置*/b.databno.j=a.dataano.i;b.databno.i=a.dataano.j;for(i=0;ia.terms;i+)/*输出转置后的三元组结果*/printf(%5d%5d%5
23、dn,b.datai.i,b.datai.j,b.datai.v);void main()int i;struct sparmatrix a;scanf(%d%d%d,/*调用转置算法*/,54,分析这个算法,主要工作在col和ano二重循环上,故算法的时间复杂度为 O(a.cols*a.terms)。而通常的mn阶矩阵转置算法可描述为:for(col=0;coln;col+)for(row=0;rowm;row+)bcolrow=arowcol;它的时间复杂度为O(mn)。而一般的稀疏矩阵中非零元个数a.terms远大于行数m,故压缩存储时,进行转置运算,虽然节省了存储单元,但增大了时间复杂
24、度,故此算法仅适应于a.ternsa.rows a.cols的情形。,(2)按照A的行序进行转置即按a.data中三元组的次序进行转置,并将转置后的三元组放入b中恰当的位置。若能在转置前求出矩阵A的每一列col(即B中每一行)的第一个非零元转置后在b.data中的正确位置potcol(0cola.cols),那么在对a.data的三元组依次作转置时,只要将三元组按列号col放置到b.datapotcol中,之后将potcol内容加1,以指示第col列的下一个非零元的正确位置。为了求得位置向量pot,只要先求出A的每一列中非零元个数numcol,然后利用下面公式:potcol=potcol-1+
25、numcol-1 当1cola.cols,pot0=0,55,为了节省存储单元,记录每一列非零元个数的向量num可直接放入pot中,即上面的式子可以改为:potcol=potcol-1+potcol,其中1colacols。于是可用上面公式进行迭代,依次求出其他列的第一个非零元素转置后在b.data中的位置potcol。例如,对前面图5-6给出的稀疏矩阵M,有:每一列的非零元个数为pot1=2 第0列非零元个数pot2=2 第1列非零元个数pot3=2 第2列非零元个数pot4=1 第3列非零元个数pot5=0 第4列非零元个数pot6=1 第5列非零元个数pot7=0 第6列非零元个数,每一
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第五章 数组和广义表 第五 数组 广义

链接地址:https://www.31ppt.com/p-5740520.html