1. 前言
矩阵是许多科学与工程计算中经常遇到的问题,在高级语言中,通常使用二维数组来存储矩阵。然而,在矩阵的算法中,往往会出现阶数很高的矩阵中存在许多相同的元素或值为零的元素。为了节约存储空间,需要将这些矩阵进行压缩存储。如果矩阵中的元素存在一定的规律,则称这种矩阵为特殊矩阵。如果矩阵中的元素有许多的零元素且不具有规律性,则称这种矩阵为稀疏矩阵。
2. 特殊矩阵的压缩存储
(1)对称矩阵的压缩存储
在一个n阶方阵A中,若元素满足下述性质:
aij=aji 0≤i,j≤n-1
则称A为对称矩阵。
例如下图便是一个5阶对称矩阵:
图 对称矩阵示例
对称矩阵中的元素关于主对角线对称,故只要存储矩阵中上三角或下三角中的元素,让每两个对称的元素共享一个存储空间。这样,能节约近一半的存储空间。按"行优先顺序"存储主对角线(包括对角线)以下的元素:
图 对称矩阵的行优先存放
即按a00,a10,a11,……,an-1,0,an-1,1…,an-1,n-1次序存放在一个向量sa[0..n(n+1)/2-1]中(下三角矩阵中,元素总数为n(n+1)/2)。
图 对称矩阵的压缩存储
(2)三角矩阵的压缩存储
以主对角线划分,三角矩阵有上三角矩阵和下三角矩阵两种。
①上三角矩阵
如下图(a)所示,它的下三角(不包括主角线)中的元素均为常数c。
②下三角矩阵
与上三角矩阵相反,它的主对角线上方均为常数c,如下图(b)所示。
注意:
在多数情况下,三角矩阵的常数c为零。
图 三角矩阵示意图
三角矩阵中的重复元素c可共享一个存储空间,其余的元素正好有n×(n+1)/2个,因此,三角矩阵可压缩存储到向量sa[0..n(n+1)/2]中,其中c存放在向量的最后一个分量中。
(3)对角矩阵的压缩存储
所有的非零元素集中在以主对角线为中心的带状区域中,即除了主对角线和主对角线相邻两侧的若干条对角线上的元素之外,其余元素皆为零的矩阵为对角矩阵。
图 对角矩阵示意图
对角矩阵可按行优先顺序或对角线的顺序,将其压缩存储到一个向量中,并且也能找到每个非零元素和向量下标的对应关系。
3. 稀疏矩阵的压缩存储
设矩阵Amn中有s个非零元素,若s远远小于矩阵元素的总数(即s<<m×n),则称A为稀疏矩阵。稀疏因子=(s)/(m+n),若s<=0.05,则称矩阵为稀疏矩阵。
为了节省存储单元,可只存储非零元素。由于非零元素的分布一般是没有规律的,因此在存储非零元素的同时,还必须存储非零元素所在的行号、列号,才能迅速确定一个非零元素是矩阵中的哪一个元素。稀疏矩阵的压缩存储会失去随机存取功能。
其中每一个非零元素所在的行号、列号和值组成一个三元组(i,j,aij),并由此三元组惟一确定。
稀疏矩阵进行压缩存储通常有两类方法:顺序存储和链式存储。
将表示稀疏矩阵的非零元素的三元组按行优先(或列优先)的顺序排列(跳过零元素),并依次存放在向量中,这种稀疏矩阵的顺序存储结构称为三元组表。
图 稀疏矩阵和它的三元组表
为了运算方便,将矩阵的总行数、总列数及非零元素的总数均作为三元组表的属性进行描述。其类型描述为:
#define MaxSize 10000 //由用户定义
typedef int DataType; //由用户定义
typedef struct { //三元组
int i,j;//非零元的行、列号
DataType v; //非零元的值
}TriTupleNode;
typedef struct{ //三元组表
TriTupleNode data[MaxSize]; //三元组表空间
int m,n,t; //矩阵的行数、列数及非零元个数
}TriTupleTable;
矩阵的转置:
方法一:简单地交换a->data中i和j中的内容,得到按列优先顺序存储倒b->data;再将b->data重排成按行优先顺序的三元组表。
方法二:由于A的列是B的行,因此,按a->data的列序转置,所得到的转置矩阵B的三元组表b->data必定是按行优先存放的。
按这种方法设计的算法,其基本思想是:对A中的每一列col(0≤col≤a->n-1),通过从头至尾扫描三元组表a->data,找出所有列号等于col的那些三元组,将它们的行号和列号互换后依次放人b->data中,即可得到B的按行优先的压缩存贮表示。具体实现参见【动画演示】
稀疏矩阵的十字链表示:
稀疏矩阵的链式存储,就是利用链表来表示矩阵,链表中的每个结点存储稀疏矩阵中的每个非零元素。每个结点包含5个域:其中3个数据域是i、j和e,分别表示非0元素的行号、列号和元素值;两个指针域是right域和down域,right指向同一行中的下一个非零元素,down指向同一列的非零元素。
同一行的非零元素由right链接构成一个线性链表,同一列的非零元素由down链接构成一个线性链表。每个非零元素既是某一行链表的一个元素,又是某一列链表的一个元素,整个链表构成一个十字交叉的形状,这样的链表称为十字链表。
十字链表的类型描述如下:
typedef struct OLNode
{
int i,j;
DataType e;
struct OLNode *right, *down;
}OLNode,*OLink;
typedef struct
{
OLink *rowhead, *colhead;
int m, n, len;
}CrossList;
其中,i和j分表表示稀疏矩阵中非零元素的行号和列号,e表示非零元素值,right指向同一行的下一个非零元素,down指向同一列的下一个非零元素。rowhead和colhead分别存放指向行链表和列链表的指针,m和n分别表示稀疏矩阵的行数和列数,len表示稀疏矩阵中非零元素的个数。
分享到:
相关推荐
头歌数据结构图的邻接矩阵存储及遍历操作 第1关图的邻接矩阵存储及求邻接点操作 第2关图的深度优先遍历 第3关图的广度优先遍历 稳过
无向图的邻接矩阵存储及输出无向图的邻接矩阵存储及输出
图的邻接矩阵存储和邻接表存储 代码完整 有注释,有需要的可以下载看看,基本是图的邻接矩阵存储和邻接表存储 代码完整
图的邻接矩阵存储表示和实现图的邻接矩阵存储表示和实现图的邻接矩阵存储表示和实现,图的邻接矩阵存储表示和实现,图的邻接矩阵存储表示和实现,图的邻接矩阵存储表示和实现,图的邻接矩阵存储表示和实现,图的邻接...
图邻接矩阵的存储代码 是我话了一个晚上编写的,足够全面
用C写的用邻接矩阵存储的图的简单路径,数据结构用
建立有向图G的邻接矩阵存储,包括邻接矩阵结构,初始化等
定义采用邻接矩阵存储的图结构封装DFS、BFS算法
基于邻接矩阵存储的图的最小生成树的Prime算法,对学习C++和数据结构很有帮助
以文件操作输入邻接矩阵存储的无向图,广度和深度的递归遍历
用C语言实现,利用邻接矩阵存储图的程序,建立图用邻接矩阵存储,输出邻接矩阵,并用深度优先算法遍历二叉树
1. Re:随机采样方法整理与讲解 2. Re:稀疏矩阵存储格式总结+存储效 3. Re:稀疏矩阵存储格式总结+存储效 4. Re:机器学习降维算法一:PCA
采用邻接矩阵实现无向图的存储,并输入输出邻接矩阵。实现图的广度优先遍历和深度优先遍历。
邻接矩阵存储的结构体中,包括一个存储边的结构体,存储每条边的信息(权值)将这个边的结构体的二维数组作为图的基本存储结构,放到单个图的结构体中每个图又包含总节点数、总边数、图的类型等信息
邻接矩阵存储图的深度优先遍历 试实现邻接矩阵存储图的深度优先遍历。 函数接口定义: void DFS( MGraph Graph, Vertex V, void (*Visit)(Vertex) ); 其中MGraph是邻接矩阵存储的图,定义如下: typedef struct ...
稀疏矩阵存储和转置及乘法 c++源代码 实现原则为:节省存储空间、跟快的运算。
对角稀疏矩阵存储系统
有关无向网的邻接矩阵存储,用C语言编写,详细代码。
图的邻接矩阵存储方式是**通过一个二维数组来表示图中顶点之间的边关系**。 在数学和计算机科学中,图是一种用来描述对象之间相互连接关系的结构。为了在计算机内表示这种结构,我们需要对图进行存储。邻接矩阵是一...
基于邻接矩阵存储的图的最短路径问题,可以很好的学习C++和数据结构