第5章 数组和广义表

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

5.4.1稀疏矩阵的存储方法 . . 稀疏矩阵的存储方法
1.三元组顺序表 在压缩存放稀疏矩阵非零元的同时,若还 存放此非零元所在的行号和列号,则称为三 元组表法,即称稀疏矩阵可用三元组表进行 压缩存储,然而,它是一种顺序存储(按行优 先顺序存放)。由一个非零元的行号、列号、 值组成一个三元组,整个稀疏矩阵中非零元 的三元组合起来称作三元组表。
(2)只存放上三角部分。对于对称矩阵,除了 可以用下三角形式存放外,还可以用上三角 形式存放,这时a[0][0]存入s[0],a[0][1]存入 s[1],a[0][2]存入s[2],…,如图5-7所示。 这时s[k]与a[i][j] 的对应关系可以按下面方法 推出: 当i≤j时, aij在上三角部分中,前面共有i行, 共有n+(n-1)+…+(n- (i-1)) = i×n-i×(i-1)/2 个元素,而aij是本行第j-i个元素,故k=i×ni×(i-1)/2+j-i,当i>j时,交换i与j即可。故s[k] 与a[i][j]的对应关系为:
只要给出一组下标便可求得相应数组元素 的存储位置。下面以行序为主序的存储结 构为例,说明如何由下标计算相应数组元 素的存储地址。 假定每个数据元素占L个存储单元,则二 维数组A中任意元素aij的存储地址由下式确 定 LOC[i,j]=LOC[0,0]+( b2×i+j)×L
其中,LOC[i,j]是aij的存储地址;LOC[0, 0]是a00的存储地址,即二维数组A的起始存 储地址,也称为基址, b2是数组第二维的长 度。 推广到一般情况,就可得到n维数组的数据 元素存储地址的计算公式(知道即可)
转置矩阵
0 14 0 0 − 5 0 −7 0 0 0 36 0 0 28 0
0 0 14 − 7 0 0 0 0 − 5 0 36 0 0 28 0
用“三元组”表示 0 0 1 2 2 1 4 1 0 3 14 -5 -7 36 28 0 1 1 3 4 2 0 1 2 0 36 14 -7 28 -5
当一个数组的每一个数组元素都含有两个 下标时,该数组称为二维数组。 可以把一个二维数组看成是每个数据元素 都是相同类型的一维数组的一维数组,这 样,也可以把二维数组看作为一个线性表。 依此类推,一个三维数组可以看作是一个 每个数据元素都是相同类型的二维数组的 一维数组。 如图5-l
在C++语言中,一个二维数组可以定义为其 分量类型为一维数组的一维数组类型,即 typedef ElemType Array2 [m][n]; 这个定义等价于 typedef ElemType Arrayl [n]; typedef Arrayl Array2[m]; 即定义了一个长度为m的线性表,表中的每 个元素是一个长度为n的线性表。
十字链表(不采用循环链表 十字链表 不采用循环链表) 不采用循环链表
M.chead
^
M.rhead
0 03
0 35
^^
1 1 -1
^^
2 02
^^
3 0 0 5 0 -1 0 0 2 0 0 0
稀疏矩阵中同一行的非零元通过向右的行指 针链接成一个带表头结点的循环链表。同一 列的非零元也通过列指针链接成一个带表头 结点的循环链表。 为了运算方便,我们规定行、列循环链表的 表头结点和表示非零元的结点一样,也定为 五个域,且规定行、列、域值为0,并且将所 有的行、列链表和头结点一起链成一个循环 链表。 书上图5-9
5.3.1 特殊矩阵 . . 特殊矩阵通常有以下几种: (1)对称矩阵:矩阵A是一个对称矩阵,当且 仅当对于所有的i和j有A(i,j)= A(j,i)。 (2)上三角矩阵:矩阵A是一个上三角矩阵, 当且仅当i>j时,有A(i,j)=0, 即主对角线的 左下方元素均为零元素的矩阵。 (3)下三角矩阵:矩阵A是一个下三角矩阵, 当且仅当i<j时,有A(i,j)=0,即主对角线的 右上方元素均为零元素的矩阵。
数据类型可描述如下: const int maxSize=100; //定义非零元的 最大数目 struct Node //定义一个三元组 { int i,j; //非零元行、列号 int v: //非零元的值 };
struct SparMatrix //定义稀疏矩阵 { int rows,cols; //稀疏矩阵行、 列数 int terms; //稀疏矩阵非零 元个数 Node data[maxSize]; //三元组表 };
2.十字链表的概念和C++类定义 当稀疏矩阵中非零元的位置或个数经常变动 时,三元组就不适合作稀疏矩阵的存储结构 了,此时采用十字链表作为存储结构是一种 较好的方法。在该方法中,每一个非零元用 一个结点表示,结点中除了表示非零元所在 的行、列和值的三元组(i,j,v)外,还需增加 两个链域:行指针域,用来指向本行中下一 个非零元素;列指针域,用来指向本列中下 一个非零元素。
5.4 稀疏矩阵
在实际应用中,经常会遇到一类矩阵:其矩 阵阶数很大,非零元个数较少,零元很多, 但非零元的排列(分布)没有一定规律,我们称 这一类矩阵为稀疏矩阵。 按照压缩存储的概念,要存放稀疏矩阵的 元素,由于没有规律,除存放非零元的值外, 还必须存储适当的辅助信息(行、列号),才能 迅速确定一个非零元是矩阵中的哪一个位置 上的元素。
5.2数组的顺序存储与寻址
数组具有有序性,即数组中每个元素是有序 的,并且元素之间的次序是不能改变的。对 数组的操作除创建和销毁外,只有取数组中某 一元素和修改某一元素的值的操作,没有插入 和删除操作,因此,采用顺序存储结构表示数 组是最好的方式。
由于计算机内存单元是一维的结构,而数 组可能是一维的也可能是多维的,所以用 一组连续存储单元存放数组的数据元素就 有排列顺序的问题。 二维数组有两种存储方式:一种以列序为 主序的存储方式,即先存储第一列数据元 素,接着存储第二列数据元素,最后存储 第n列数据元素,另一种是以行序为主序的存 储方式,先存储第一行数据元素,接着存 储第二行数据元素,最后存储第m行数据元 素,如图5-2所示。 各种语言存储方式不同
5.4.2基于三元组表的稀疏矩阵的转置 矩阵转置是一种最简单的矩阵运算。对于一 个m×n的矩阵M,它的转置矩阵N是一个 n×m的矩阵,且N(i,j)=M(j,i),1≤i≤n, 1≤j≤m。很明显,一个稀疏矩阵的转置矩阵 仍然是一个稀疏矩阵。
要实现三元组顺序表示矩阵的转置,只 需实现以下三点: (1)将矩阵的行列值相互交换; (2)将每个三元组中的i和j相互调换; (3)重新排列三元组之间的顺序便可实现矩 阵的转置。 有两种实现稀疏矩阵的转置的方法。 设a和b分别是转置前和转置后的三元组。
void transpose(SparMatrix a,SparMatrix b) {// a和b分别是转置前和转置后的三元组表 b.rows=a.cols; b.cols=a.rows; b.terms=a.terms; if(b.terms>0) { int bnoBiblioteka Baidu0;
for(int col=0;col<a.cols;col++) //按列扫描 for(int ano=0;ano<a.terms;ano++) //对三 元组表扫描 if(a.data[ano].j= =co1) //进行转置 { b.data[bno].j=a.data[ano].i; b.data[bno].i=a.data[ano].j; b.data[bno].v=a.data[ano].v; bno++; }
5.3 特殊矩阵及其压缩存储
矩阵是一个二维数组,矩阵可以用行优先顺序或列 优先顺序的方法顺序存放到内存中,但是,当矩阵 的阶数很大时,将会占用较多的存储单元。而当里 面的元素分布呈现某种规律时,从节约存储出发, 可考虑若干元素共用一个存储单元,即进行压缩存 储。压缩存储是指:为多个值相同的元素只分配一 个存储空间,值为零的元素不分配空间。但是,在 进行压缩存储时,虽然节约了存储单元,但要在压 缩存储后直接访问数组元素, 还必须给出压缩前下 标(二维数组的行、列)值和压缩后一维数组的下标 值之间的变换公式。
一般地,可以借助线性表的概念递归地定 义n维数组: 一个n维数组是一个元素可直接寻址的线性 表 A = ( A1,A2, … ,An) 若Ai 是简单元素(不是数组), 则A是一维数组, 若Ai 是k-1维数组, 则A是k维数组, 其中 i=1,2,…,n, k是大于0的整数。
数组的性质: (1)数组中的数据元素数量固定。一旦定义 了一个数组,它的维数和维界就不能再改 变,只能对数组进行存取元素和修改元素 值的操作; (2)数组中的数据元素具有相同的数据类型; (3)数组中的每个数据元素都和一组唯一的 下标对应; (4)数组是一种随机存储结构,可随机存取 数组中的任意数据元素。
1. 按照列序进行转置 按照表b.data的三元组的次序,依次在表 a.data中找到相应的三元组,然后进行转置, 即按照矩阵M的列序来进行转置。由于M的 列即为N的行,在表a.data中,按列扫描,所 以得到的b.data必按行主序存放。为了找到M 的每一列中所有的非零的元素,每次都必须 从头到尾扫描M的三元组表,算法的C++代码 如下:
(2)下三角矩阵。 与上面推导类似,下三角矩阵中s[k]和aij之间 的对应关系为 3.对角矩阵的压缩存储(了解) 总而言之,对特殊矩阵如对称矩阵、三角矩 阵、对角矩阵等的压缩方法是:找出这些特 殊矩阵中元素的分布规律,把那些有一定分 布规律的、值相同的元素(包括零元素)压缩存 储到一个存储空间中。这样的压缩存储只需 要在算法中按公式作一个映射,即可实现矩 阵元素的随机存取。
仅以行主序存放分两种方式讨论。 (1)只存放下三角部分。由于对称矩阵关于 对角线对称,故只需存放主对角线及主对角 线以下的元素。这时,a[0][0]存入s[0], a[1][0]存入s[1],a[1][1]存入s[2],…, 如图5-6所示。
从上面的对应关系容易推出:当i≥j时,aij在 下三角部分中,aij前面有i行,共有 1+2+3+…+i个元素,而aij是第i行的第j个元素, 即有k=1+2+3+…+i+j=i(i+1)/2+j;当i<j时,aij 在上三角部分中,但与a对称,故只需在下三 角部分中找aij即可,故只需将i与j交换即可, 即k=j(j+1)/2+i。
第5章 数组和广义表
数组和广义表可以看成是线性表的推广, 它们与前面讨论的线性结构不同,前面的线 性结构是原子类型的,而数组和广义表的数 据结构是结构化类型的,即元素的值是可以 再分解的。
5.1数组的定义及抽象数据类型表示
5.1.1 数组的定义 . . 数组(Array)是由一组类型相同的数据元素构成的有 数组 限序列,且该有限序列存储在一块地址连续的内存 单元中。数据元素可以是整数、实数等简单类型, 也可以是数组、结构等构造类型。数组元素在数组 中的相对位置由其下标来确定。 若数组只有一个下标,这样的数组称为一维数组, 把数据元素的下标变成线性表中的位序,则一维数 组就是一个线性表。
• 2.三角矩阵的压缩存储 • (1)上三角矩阵。 • 上三角矩阵中,主对角线之上的第p行(0≤p<n) 恰有n-p个元素,按行主序存放上三角矩阵中的 元素aij时,aij元素前有i行(从第0行到第i-1行), 一共有(n-0)+(n-1)+(n-2)+…+(n-i+1)= i (2n-i+1) /2个元素;在第i行上,aij之前恰有j-i个元素(即 aii,aii+1,…,aij-1),因此有s[i (2n-i+1)/2+ji]= aij。 • 所以,地址k的计算公式为
(4)对角矩阵:对角矩阵是所有的非零元均 集中在以对角线为中心的带状区域中的n阶 方阵。即除了主对角线上和直接在对角线 上、下方若干条线上的元素之外,所有其 他的元素皆为0。
5.3.2 特殊矩阵的压缩存储 . .
1.对称矩阵的压缩存储 设矩阵An×n是对称的,对称的两个元素可以共用 一个存储单元,这样,原来n阶方阵需n2个存储单 元,如采用压缩存储,仅需n(n+1)/2个存储单元, 节约将近一半存储空间。 将n阶对称方阵存放到一个向量空间s[0]到 s[n(n+1)/2一1]中,并找到s[k]与a[i][j]的一一对应关 系从而使在s[k]中直接访问a[i][j]的方法。
相关文档
最新文档