第5章数组和稀疏矩阵

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{ int i,k=0;
if (rs>=t.rows || cs>=t.cols) return 0; while (k<t.nums && rs>t.data[k].r) k++; /*查找行*/ while (k<t.nums && cs>t.data[k].c) k++; /*查找列*/
if (t.data[k].r==rs && t.data[k].c==cs) t.data[k].d=x; /*存在这样的元素
例5.1 对二维数组float a[5][4]计算: (1) 数组a中的数组元素数目; (2) 若数组a的起始地址为2000,且每个数组元素长 度为32位(即4个字节),数组元素a[3][2]的内存地址。
解:由于C语言中数组的行、列下界均为0, 该数组行上界为5-1=4,列上界为4-l=3,所以该数 组的元素数目共有(4-0+1)*(3-0+1)=5*4=20个。
对一个已知以行序为主序的计算机系统中,当二 维数组第一个数据元素a1,1的存储地址LOC(a1,1)和每 个数据元素所占用的存储单元k确定后,则该二维数组 中任一数据元素ai,j的存储地址可由下式确定:
LOC(ai,j)=LOC(a1,1)+[(i-1)*n+(j-1)]*k
其中n为列数。
同理可推出在以列序为主序的计算机系统中有: LOC(ai,j)=LOC(a1,1)+[(j-1)*m+(i-1)]*k 其中m为行数。
void CreatMat(TSMatrix &t,ElemType A[M][N]) { int i,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;
下三角矩阵:
i *(i 1)+j 2
k= n(n 1) 2
i≥j时 i<j时
2. 对角矩阵的压缩存储 若一个n阶方阵A满足其所有非零元素都集中在
以主对角线为中心的带状区域中,则称其为n阶对角 矩阵。其主对角线上下方各有b条次对角线,称b为 矩 阵 半 带 宽 ,(2b+1) 为 矩 阵 的 带 宽 。 对 于 半 带 宽 为 b(0≤b≤(n-1)/2)的对角矩阵,其|i-j|≤b的元素ai,j不为零, 其余元素为零。下图所示是半带宽为b的对角矩阵 示意图。
第5章 数组和稀疏矩阵
5.1 数组 5.2 稀疏矩阵
本章小结
5.1.1 数组的基本概念
数组是n(n>1)个相同类型数据元素a1,a2,…,an构 成的有限序列,且该有限序列存储在一块地址连续的 内存单元中。
由此可见,数组的定义类似于采用顺序存储结构 的线性表。
数组具有以下性质:
(1) 数组中的数据元素数目固定。一旦定义了一 个数组,其数据元素数目不再有增减变化。
对于二维数组来说,由于计算机的存储结构是线 性的,如何用线性的存储结构存放二维数组元素就 有一个行/列次序排放问题。
以行序为主序的存储方式:即先存储第1行,然 后紧接着存储第2行,最后存储第m行。此时,二维数 组的线性排列次序为:
a1,1,a1,2,…,a1,n,a2,1,a2,2,…,a2,n,…,am,1,am,2,…am,n
按列优先的存储次序: A[0][0][0][0], A[1][0][0][0], A[0][1][0][0], A[1][1][0][0], A[0][0][1][0], A[1][0][1][0], A[0][1][1][0], A[1][1][1][0], A[0][0][0][1], A[1][0][0][1], A[0][1][0][1], A[1][1][0][1], A[0][0][1][1], A[1][0][1][1], A[0][1][1][1], A[1][1][1][1]
if (m!=n) printf("m≠n"); else { for (i=0;i<m;i++) s=s+A[i][i];
/*求第一条对角线之和*/ for (i=0;i<n;i++) s=s+A[n-i-1][i];
/*累加第二条对角线之和*/ s-=A[n/2][n/2]; printf("s=%d\n",s); } }
A67
0
0
0
5
0
0
0
0 0 0 0 6 0 0
0 0 0 0 0 7 4
一个稀疏矩阵A
若把稀疏矩阵的三元组线性表按顺序存储结构 存储,则称为稀疏矩阵的三元组顺序表。则三元 组顺序表的数据结构可定义如下:
#define MaxSize 100 /*矩阵中非零元素最多个数*/
typedef struct
{ int s=0,i=0,j=0;
do
{ do
{ s=s+A[i][j];
j=j+2;
/*跳过一列*/
} while (j<n); i=i+1;
/*下一行*/
if (j==0) j=1;
else j=0;
} while (i<m);
printf("s=%d\n",s);
}
(3) 对应算法如下:
void proc3(maxix A) { int i,s=0;
b条
...
0
b条
...
0
半带宽为b的对角矩阵
A ←→ B a[i][j] ←→ b[k]
当b=1时称为三对角矩阵。 其压缩地址计算公式如下:
k=2i+j
例5.2 按行优先顺序和按列优先顺序列出 四维数组A[2][2][2][2]所有元素在内存中的 存储次序。
解: 按行优先的存储次序:
A[0][0][0][0], A[0][0][0][1], A[0][0][1][0], A[0][0][1][1], A[0][1][0][0], A[0][1][0][1], A[0][1][1][0], A[0][1][1][1], A[1][0][0][0], A[1][0][0][1], A[1][0][1][0], A[1][0][1][1], A[1][1][0][0], A[1][1][0][1], A[1][1][1][0], A[1][1][1][1]
例5.3 对于二维数组A[m][n],其中m≤80,n≤80,先 读入m和n,然后读该数组的全部元素,对如三种情况 分别编写相应函数:
(1) 求数组A靠边元素之和;
(2) 求从A[0][0]开始的行、列互不相邻的各元素 之和;
(3) 当m=n时,分别求两条对角线上的元素之和, 否则打印出m≠n的信息。
5.2 稀疏矩阵
一个阶数较大的矩阵中的非零元素个数s相对 于矩阵元素的总个数t十分小时,即s<<t时,称该矩阵 为稀疏矩阵。例如一个100×100的矩阵,若其中只 有100个非零元素,就可称其为稀疏矩阵。
5.2.1 稀疏矩阵的三元组表示
稀疏矩阵的压缩存储方法是只存储非零元素。
由于稀疏矩阵中非零元素的分布没有任何规律,所 以在存储非零元素时还必须同时存储该非零元素所 对应的行下标和列下标。这样稀疏矩阵中的每一个 非零元素需由一个三元组(i,j,ai,j)惟一确定,稀疏矩阵 中的所有非零元素构成三元组线性表。
又由于C语言采用行序为主序的存储方式,则 有:
LOC(a3,2)=LOC(a0,0)+(i*n+j)*k
=2000+(3*4+2)*4=2056
5.1.3 特殊矩阵的压缩存储
特殊矩阵是指非零元素或零元素的分布有一定规 律的矩阵,为了节省存储空间,特别是在高阶矩阵的情 况下,可以利用特殊矩阵的规律,对它们进行压缩存储, 也就是说,使多个相同的非零元素共享同一个存储单 元,对零元素不分配存储空间。
t.data[t.nums].d=A[i][j];t.nums++; } } }
(2) 三元组元素赋值
先在三元组t中找到适当的位置k,将k~t.nums个 元素后移一位,将指定元素x插入到t.data[k]处。算 法如下:
int Value(TSMatrix &t,ElemType x,int rs,int cs)
LOC(ai)=LOC(a1)+(i-1)*k (0≤i≤n)
上式说明,一维数组中任一数据元素的存储地址可 直接计算得到,即一维数组中任一数据元素可直接存 取,因此,一维数组是一种随机存储结构。同样,二维及 多维数组也满足随机存储特性。
对于一个m行n列的二维数组Am×n,有:
a1,1
Amn
a2,1
am,1
a1,2 a2,2
am,2
a1,n
a2,n
am,n
将Am*n简记为A,A是这样的一维数组: A=(a1,a2,…,ai…,am)
其中,ai=(ai,1,ai,2,…,ai,n) (1≤j≤m)。
显然,二维数组同样满足数组的定义。一个 二维数组可以看作是每个数据元素都是相同类 型的一维数组的一维数组。以此类推,任何多维 数组都可以看作一个线性表,这时线性表中的每 个数据元素也是一个线性表。多维数组是线性 表的推广。
特殊矩阵的主要形式有对称矩阵、对角矩阵等,它 们都是方阵,即行数和列数相同。
1. 对称矩阵的压缩存储
若 一 个 n 阶 方 阵 A[n][n] 中 的 元 素 满 足 ai,j=aj,i(0≤i,j≤n-1),则称其为n阶对称矩阵。
由于对称矩阵中的元素关于主对角线对称,因此 在存储时可只存储对称矩阵中上三角或下三角中的 元素,使得对称的元素共享一个存储空间。这样,就 可以将n2个元素压缩存储到个元素的空间中。不失 一般性,我们以行序为主序存储其下三角(包括对角 线)的元素。
解: (1) 对应算法如下:
void proc1(ElemType A[][n]) { int s=0,i,j;
for (i=0;i<m;i++) /*第一列*/ s=s+A[i][0];
for (i=0;i<m;i++) /*最后一列*/ s=s+A[i][n-1];
for (j=0;j<n;j++) /*第一行*/ s=s+A[0][j];
假设有一个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))
0 Fra Baidu bibliotek 1 0 0 0 0
0
2
0
0
0
0
0
3 0 0 0 0 0 0
(2) 数组中的数据元素具有相同的数据类型。
(3) 数组中的每个数据元素都和一组惟一的下标 值对应。
(4) 数组是一种随机存储结构。可随机存取数组 中的任意数据元素。
5.1.2 数组的存储结构
在一维数组中,一旦a1的存储地址LOC(a1)确定,并 假设每个数据元素占用k个存储单元,则任一数据元素 ai的存储地址LOC(ai)就可由以下公式求出:
} TSMatrix;
/*三元组顺序表定义*/
其中,data域中表示的非零元素通常以行序为主 序顺序排列,它是一种下标按行有序的存储结构。 这种有序存储结构可简化大多数矩阵运算算法。 下面的讨论假设data域按行有序存储。
(1) 从一个二维矩阵创建其三元组表示
以行序方式扫描二维矩阵A,将其非零的元素插入到 三元组t的后面。算法如下:
for (j=0;j<n;j++) /*最后一行*/ s=s+A[m-1][j];
s=s-A[0][0]-A[0][n-1]-A[m-1][0]-A[m-1][n-1]; /*减去4个角的重复元素值*/
printf("s=%d\n",s); }
(2) 对应算法如下:
void proc2(maxix A)
n2个元素←→ n(n+1)/2个元素 A[0..n-1,0..n-1] ←→ B[0..n(n+1)/2-1]
a[i][j] ←→ b[k]
i(i 1)
k=
2 + j i≥j j(j 1) + i i<j
2
上三角矩阵:
i*(2ni 1) + j – i i≤j时 2
k=
n(n 1) 2
i>j时
{ int r;
/*行号*/
int c;
/*列号*/
ElemType d; /*元素值*/
} TupNode;
/*三元组定义*/
typedef struct
{ int rows;
/*行数值*/
int cols;
/*列数值*/
int nums;
/*非零元素个数*/
TupNode data[MaxSize];
相关文档
最新文档