数据结构(C++)矩阵的压缩

首先引入两个概念:

特殊矩阵:矩阵中很多值相同的元素并且它们的分布有一定的规律。
稀疏矩阵:矩阵中有很多零元素。

压缩存储的基本思想是:

⑴ 为多个值相同的元素只分配一个存储空间;
⑵ 对元素不分配存储空间。

特殊矩阵的压缩存储——对称矩阵

在这里插入图片描述
在对角线的两边,aij==aji,这里出现了不必要的多于存储,所以我们对其进行矩阵的压缩。
这里只演示二维数组从0,0开始的
在这里插入图片描述
这分别是我们的二维数据中的下三角矩阵,和其保存为一维数组的存储说明图,下图更清楚地描述在一维数组里的结构:
在这里插入图片描述
首先假设一位数字的位置用k表示,二维数组用i、j表示,经过我们的推理不难发现,i、j、k之间存在一定的数量关系。

  • a[i][j]在一维数组里的序号=i*(i+1)/2+j+1
  • a[i][j]在一维数组里的下标=i*(i+1)/2+j

压缩对称矩阵的代码实现:

依旧是使用了刚才的那组数据,进行了压缩

#include<iostream>
using namespace std;
int main()
{
	int a[5][5] = { 3,6,4,7,8,6,2,8,4,2,4,8,1,6,9,7,4,6,0,5,8,2,9,5,7 };
	int n = 5, k = 0;
	int b[15];
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			k = i * (i + 1) / 2 + j;
			b[k] = a[i][j];
		}
	}
	for (int i = 0; i < n * (n + 1) / 2; ++i)
	{
		cout << b[i] << " ";
	}
	return 0;
}

三角矩阵的压缩:

三角矩阵的样貌:
在这里插入图片描述
其实三角矩阵与对称矩阵有着很多类似的地方,比如如果是下三角矩阵,下三角的各个位置还是依旧对应着一维数组里的位置,唯一不同的是,一维数组还要再多加一个数据,就是上三角中相同的c
一维数组存储图:
在这里插入图片描述
三角矩阵里i、j、k的对应关系:(依旧是从0,0开始)
在这里插入图片描述

这里以下三角矩阵为例进行代码演示:

c用0来代替

#include<iostream>
using namespace std;
int main()
{
	int a[5][5] = { 3,0,0,0,0,6,2,0,0,0,4,8,1,0,0,7,4,6,0,0,8,2,9,5,7 };
	int n = 5, k = 0;
	int b[16];
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			k = i * (i + 1) / 2 + j;
			b[k] = a[i][j];
		}
	}
	b[15] = 0;
	for (int i = 0; i <= n * (n + 1) / 2; ++i)
	{
		cout << b[i] << " ";
	}
	return 0;
}

对角矩阵的压缩

对角矩阵:所有非零元素都集中在以主对角线为中心的带状区域中,除了主对角线和它的上下方若干条对角线的元素外,所有其他元素都为零
在这里插入图片描述

二维数组法:

在这里插入图片描述
把对角上的元素全部有序的整理在一个二位数组中,第一位和最后一位都是0,然后用一个新的b数组进行顺序存储。
原B上的数组下标与新B有着一定规律的对应关系,不难发现:t=i-1,s=j-i+1
**一维数组的存储图:*一共3n-2个元素
在这里插入图片描述
i、j、k对应的关系:(略微复杂)
在这里插入图片描述
这里就不用代码实现了,纯粹就是一个找规律,但是自己确实不知道如何去找这个规律。这个对角矩阵的压缩的思想经过总结后,分为以下几步:

  1. 先把对角矩阵的相关数据取下来,保留原先的 i、j 下标不变。
  2. 将截取下来的二维数组变换下标,从0,0开始,使之成为一个顺序的二维数组。
  3. 把这个顺序的二维数组压缩成为一维数组进行保存。

下个周一定要做一次n=7的数组,取对角元素自己找一下规律训练一下。机器都会学习了,自己也要继续学习。



稀疏矩阵的压缩存储

稀疏矩阵的排列除了有部分值不为0之外,其他的值都是0,所以相比刚刚的对角矩阵,实现起来就友好很多。这里运用到了结构体类相关的知识,因为一个数据类型保存多个值。
在这里插入图片描述
这里引入三元组表的概念。

三元组表:将稀疏矩阵的非零元素对应的三元组所构成的集合,按行优先的顺序排列成一个线性表。

在这里插入图片描述
item代表这个元素值,row、col分别代表这个元素所在的位置。

template <class T>
struct element
{
	int row, col;     //行号,列号
	T item              //非零元素值
};

三元组表的存储说明:(三元组表最后的数据信息是整个矩阵的非零元素个数、行、列)
在这里插入图片描述
存储结构定义:

const int MaxTerm = 100;
template <class T>
struct SparseMatrix
{
	T data[MaxTerm];   //存储非零元素
	int mu, nu, tu;           //行数,列数,非零元个数
};

同样,十字链表也可以表示稀疏矩阵的压缩

采用链接存储结构存储三元组表,每个非零元素对应的三元组存储为一个链表结点,结构为:
在这里插入图片描述
row:存储非零元素的行号
col:存储非零元素的列号
item:存储非零元素的值
right:指针域,指向同一行中的下一个三元组
down:指针域,指向同一列中的下一个三元组

template<class T>
class OLNode
{
private:
	int row, col;
	T element;
	OLNode<T>* right, * down;
public:
	OLNode() { right = NULL; down = NULL; };
};

十字链表的存储示意图:

在这里插入图片描述

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值