2021-09-20 矩阵的压缩存储

矩阵的压缩存储
1.特殊矩阵(上三角,下三角化为一维数组存储)
2.稀疏矩阵
(1)三元组表

 struct tuple3p
 {
	int i,j;
	elementype val;
	}
 struct sparmattp
 {
  int   mu,tu,tu;//分别代表稀疏矩阵的行值,列值,非零元个数
  tuple3p data[100001];
  }a,b;
在这种条件下实现转制和相乘
  • 转置(转置前矩阵为M(mn),用sparmattp型的a来描述,转置后矩阵为N(nm),用sparmattp型的b来描述)

方法一:一般转置方法

	for (int i=1;i<=m;i++)
		for(int j=1;i<=n;j++)
		{
		 N[col][row]=M[row][col];
		 }
时间复杂度O(m*n)

方法二:按照b.data中三元组的次序依次在a.data中找到相应的三元组进行转置(按照矩阵M的列序进行转置)

void trans_sparmat(sparmattp a,sparmattp b)
	{
			b.mu=a.nu;b.nu=a.mu;b.tu=a.tu;
			if (b.tu!=0)
			{
				q=1;//q☞b.data中三元组的序号
				for(int col=1;col<=a.nu;col+++)//扫描a.data a.nu遍
				//(按照a中的列来检索)
					for(int p=1;p<=a.tu;p++)//扫描整个a
					if (a.data[p].j==col)//符合条件的a元素
					{
						b.data[q].i=a.data[p].j;
						b.data[q].j=a.data[p].i;
						b.data[q].val=a.data[p].val;
						q++;
					}
			}
	}
复杂度分析:时间复杂度O(mu*tu);
容易看出适用于tu<<mu*nu的情况(元素特别少矩阵特别稀疏),否则复杂度
增加至O(m*n*n);

法三:快速转置
原理:对第一种算法实现优化,预先确定矩阵M中每一列的第一个非零元素在b.data中应有的位置。这样转置时可将a.data中元素快速放到正确位置上去。

新设置两个数组num,cpot
num[col]:矩阵M中第col列中非零元素的个数
cpot[col]:M中第col列的第一个非零元在b.data中的位置

  • cpot[1]=1;
  • cpot[col]=cpot[col-1]+num[col-1]; col∈[2,a.nu]
void fast_transpos(sparmattp a,sparmattp b)
	{
			b.mu=a.nu;b.nu=a.mu;b.tu=a.tu;
			if (b.tu!=0)
			{
				q=1;//q☞b.data中三元组的序号
				for(int col=1;col<=a.nu;col+++)//扫描a.data a.nu遍
					num[col]=0;
				for(int t=1;t<=a.tu,t++)
					num[a.data[i].j]+=1;
					//求M中每一列非零元个数
				cpot[1]=1;
				for(int col=2;col<=a.nu;col+++)
					cpot[col]=cpot[col-1]+num[col-1];
					//求第col列中第一个非零元在b.data中的序号
				for(int p=1;p<=a.tu;p++)//扫描整个a,转置
					{
					    col=a.data[p].j;//直接知道这个元素是哪一列的
					    q=cpot[col];
					    //这一列的元素该在b.data的哪个位置开始存储
						b.data[q].i=a.data[p].j;
						b.data[q].j=a.data[p].i;
						b.data[q].val=a.data[p].val;
						cpot[col]+=1;
			//下次再遇到这一列的元素就要存储在现在这个位置之后一个位置
					}
			}
	}
复杂度分析:O(mu+tu)
均为单循环,最坏情况(tu=mu*nu)复杂度降为O(m*n),和经典算法复杂度一致
  • 相乘
    法一:M:m1n1 则N m2n2
    当n1=m2时有(最终是一个m1*n2矩阵)
for(int i=1;i<=m1;i++)
	for (int j=1;j<=n2;j++)
	{
		Q[i][j]=0;
		for(int k=1;k<=n1;k++)
		Q[i][j]+=M[i][k]+N[k][j];
	}
时间复杂度O(m1*n1*n2)
很明显这个算法不能用于M,N是稀疏矩阵且用三元组表作存储结构时

优化思路:
(1)0*任何数为0,故稀疏矩阵中只需要a.data中下标为[i][k]和b.data中下标为[k][j]中不为零的元素相乘就可以了
☞为了便于在b.data中寻找矩阵N中第k行的所有非零元,和转置中的思想类似,附设数组rpos[m2+2],num[m2+2]:

  • rpos[1]=1;
  • rpos[row]=rpow[row-1]+num[row-1]

rpos[row]:N中第row行中第一个非零元在b.data的序号
rpos[row+1]-1:N中第row行中最后一个非零元在b.data中的序号
(为了确定最后一行的最后一个非零元的序号,数组需要开到m2+2,而不是m2+1)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值