数组的压缩存储(特殊矩阵&稀疏矩阵)

几种特殊数组

其实这里就不应该说是数组了,而应该是说行列式,

  1. 对称矩阵:a[i][j]=a[j][i]
  2. 上下三角行列式:对角线以下/以上的元素均为0
  3. 带状行列式:这个可能不太好理解,举一个例子
    1 1 0 0 0
    1 1 1 0 0
    0 1 1 1 0
    0 0 1 1 1
    0 0 0 1 1
    这时看对角线比较舒服,可以看出来有三条斜着的线上的元素是aij(例子里面均是1),而剩下的是0.
    介绍一个名词,带宽,就是带状行列式的宽度,为第一行非零元格个数减一,记为s。

存储

因为上述矩阵的特点(声明一下,行列式也可以看成矩阵,至少在我学习的范围内,含义上可能有所不同,但并不影响对这部分知识的阐述),这些矩阵都可以只存储非零元,或者是对称部分的一半,这样就可以节约很多的空间。
采取一元矩阵的结构,这样每一种应该怎么放置呢?

对称阵:a[i][j]
如果i>=j,应该为一元数组的b[ i*(i+1)/2 + j ];
如果i<j,则变成b[j*(j+1)/2 + i ]; //因为是一样的其实就是取出a[j][i]
就是一个简单的找规律问题,不必多说了。
(等号的位置不影响结果)

对称阵这里有一个细节哈,就是按照上三角和下三角存储的一维数组顺序不一样,上述公式是上三角按行存储的,如果需要下三角按行存储,按照相同的原理推一下就行。

上三角:
i>j的直接为0;
i<=j的b[ i*(i+1)/2 + j ];

下三角:
i>=j 时 b[ i*(i+1)/2 + j ];
i<j为0;

带状矩阵:
|i-j|<=s,b[2s*i+j] (s为前面提到的带宽)

其实上下三角的问题(包括对称),是按照行来存储,也可以按照列,对称阵里面也是上下三角存储均可,上述只是一种方式,并不唯一,如果实际操作还是建议按照自己舒服的方式来,现场推导一下。

稀疏矩阵的压缩存储

一个二维数组的非零元个数远少于零元个数且无序分布的时候。
一般的限定为非零元个数比例少于5%

方法一:三元组存储

struct three
{
    int row;//行
    int col;//列
    int value;//值
};

一般用这样一个三元组存储。
只需要一个结构体数组即可。

方法二:十字链表
在这里插入图片描述
这样的结构体

struct three
int row,col;//行列信息
int value;//数值信息
struct three *left,*up;//两个指针

这个指针是怎么用的?

在这里插入图片描述
没错,用来连接整个链表的(十字表)

结构:
需要两个结构体数组,
一个长度为行数,列值初始化为-1,up指针为空,left指针初始化指向自己。
另一个长度为列数,行初始化为-1,left指针为空,up指针初始化指向自己。

每插入一个点,需要匹配行列数组上的结构体,将left指针指向对应行的结构体,并将行的left指针指向该节点,保证构成环,列同理;
如果之前该行或者该列有元素,按照环形链表的方式处理即可。

就这样,每一行每一列都是一个环形链表。
在这里插入图片描述
上述图案对应的矩阵。

说明一下,正常情况看left和up指针可能很别扭,你也可以换成向右和向下的指针,只要知道是使用两个指针连接整个十字链表就行了,另外我在其他博客上也看到了不构成环形链表的,但是看得出来思想都是一样的,具体细节完全可以看个人的习惯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值