数据结构实验五矩阵的压缩存储与运算

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

第五章矩阵的压缩存储与运算

【实验目的】

1. 熟练掌握稀疏矩阵的两种存储结构(三元组表和十字链表)的实现;

2. 掌握稀疏矩阵的加法、转置、乘法等基本运算;

3. 加深对线性表的顺序存储和链式结构的理解。

第一节知识准备

矩阵是由两个关系(行关系和列关系)组成的二维数组,因此对每一个关系上都可以用线性表进行处理;考虑到两个关系的先后,在存储上就有按行优先和按列优先两种存储方式,所谓按行优先,是指将矩阵的每一行看成一个元素进行存储;所谓按列优先,是指将矩阵的每一列看成一个元素进行存储;这是矩阵在计算机中用一个连续存储区域存放的一般情形,对特殊矩阵还有特殊的存储方式。

一、特殊矩阵的压缩存储

1. 对称矩阵和上、下三角阵

若n阶矩阵A中的元素满足= (0≤i,j≤n-1 )则称为n阶对称矩阵。对n阶对称矩阵,我们只需要存储下三角元素就可以了。事实上对上三角矩阵(下三角部分为零)和下三角矩阵(上三角部分为零),都可以用一维数组ma[0.. ]来存储A的下三角元素(对上三角矩阵做转置存储),称ma为矩阵A 的压缩存储结构,现在我们来分析以下,A和ma之间的元素对应放置关系。

问题已经转化为:已知二维矩阵A[i,j],如图5-1,

我们将A用一个一维数组ma[k]来存储,它们之间存在着如图5-2所示的一一对应关系。

任意一组下标(i,j)都可在ma中的位置k中找到元素m[k]= ;这里:

k=i(i+1)/2+j (i≥j)

图5-1 下三角矩阵

a00 a10 a11 a20 … an-1,0 … an-1,n-1

k= 0 1 2 3 …n(n-1)/2 …

n(n+1)/2-1

图5-2下三角矩阵的压缩存储

反之,对所有的k=0,1,2,…,n(n+1)/2-1,都能确定ma[k]中的元素在矩阵A中的位置(i,j)。这里,i=d-1,(d是使sum= > k的最小整数),j= 。

2. 三对角矩阵

在三对角矩阵中,所有的非零元素集中在以主对角线为中心的带内状区域中,除了主对角线上和直接在对角线上、下方对角线上的元素之外,所有其它的元素皆为零,见图5-3。

图5-3 三对角矩阵A

与下三角矩阵的存储一样,我们也可以用一个一维数组ma[0..3n-2]来存放三对角矩阵A,其对应关系见图5-4。

a00 a01 a10 a11 a12 … an-1,n-2 an-1,n-1

k= 0 1 2 3 4 …

3n-3 3n-2

图5-4下三角矩阵的压缩存储

A中的一对下标(i,j)与ma中的下标k之间有如下的关系:

公式中采用了C语言的符号,int()表示取整,‘%’表示求余。

二、稀疏矩阵

在m×n的矩阵中,有t个非零元。令δ=,称δ矩阵的稀疏因子,常认为δ≤0.05时称为稀疏矩阵。稀疏矩阵在工程中有着大量的应用,不少工程问题都可以转化为对稀疏矩阵的计算问题。如何进行稀疏矩阵的压缩存储呢?

为节省存储空间,应只存储非零元素。除了存储非零元的值之外,还必须记下所在行和列的位置(i,j),即一个三元组(i,j, )唯一确定了矩阵A的一个非零元素。

1. 三元组顺序表

以顺序存储结构来表示三元组表,则可称稀疏矩阵的一种压缩存储方式。

//稀疏矩阵的三元组顺序表存储表示。

#define MaxSize 10 //用户自定义

typedef int Datatype; //用户自定义

typedef struct{ //定义三元组

int i; //非零元的行下标

int j; //非零元的列下标

Datatype v; //非零元的数据值

}TriTupleNode;

typedef struct{

TriTupleNode data[MaxSize]; //非零元的三元组表

int m,n,t; //矩阵行,列及三元组表长度

}TriTupleTable;

2. 十字链表

当矩阵的非零元个数和位置在操作过程中变化较大时,就不宜采用顺序存储结构来表示三元组的线性表,采用纵横交叉的十字链表就比较好。

在十字链表中,每个非零元可用一个含五个域的结点表示,其中i, j和e三个域分别表示该非零元所在的行、列和非零元的值,向右域right用以链接同一行中下一个非零元。向下域down用以链接同一列中下一个非零元。同一行中的非零元通过right域链接成一个线性链表,每个非零元既是某个行链表中的一个结点,又是某个列链表中的一个结点,整个矩阵构成了一个十字交叉的链表,故称这样的存储结构为十字链表,如图5-5所示。

图5-5 稀疏矩阵M的十字链表

typedef int Datatype; //用户自定义

typedef struct OLNode{

int i,j; //该非零元的行和列下标

Datatype v;

Struct OLNode *right,*down //该非零元所在行表和列表的后继链域

}OLNode;*OLink;

typedef struct {

OLink *rhead,*chead

int mu,nu,tu;

}CrossList;

第二节用三元组表实现稀疏矩阵的基本操作

【问题描述】用三元组表实现稀疏矩阵的按列转置。

【数据描述】

typedef int Datatype; //用户自定义

typedef struct

{ //定义三元组

int i,j; // 非零元素的行下标和列下标

Datatype v;

}TriTupleNode;

typedef struct{ //定义三元组表

TriTupleNode data[MaxSize];

int m,n,t; //矩阵行,列及三元组表长度

}TriTupleTable;

【算法描述】

按照列序来进行转置。为了找到每一列中所有的非零元素,需要对其三元组表从第一行起整个扫描一遍。Status TransposeSMatrix(TriTupleTable a, TriTupleTable &b){

b.m=a.n;b.n=a.m;b.t=a.t;

if(b.t){

q=0;

for(col=1;col<=a.n;++col)

for(p=0;p<=a..t;++p)

if(a.data[p].j==col){

b.data[q].i=a.data[p].j;b.data[q].j=a.data[p].i;

b.data[q].v=a.data[p].v;++q;}

}

return OK;

}

【C源程序】

#include

#include

#define Ok 1

相关文档
最新文档