`
jefferent
  • 浏览: 80523 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

矩阵的存储

阅读更多

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表示稀疏矩阵中非零元素的个数。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics