关于三元组稀疏矩阵压缩存储结构的简单转置与快速转置操作

1. 什么是稀疏矩阵?

假设m行n列的矩阵含t个非零元素,则称
a = t / (m × n) 为稀疏因子
通常认为a≤ 0.25的矩阵为稀疏矩阵。(本人老师PPT上是这样写的)

2 .稀疏矩阵压缩存储的原则?

只存储矩阵的行列维数,以及每个非零元的行列下标及其值。
例如,稀疏矩阵M如下:
在这里插入图片描述

3.三元组顺序表

(1)三元组顺序表类型描述

typedef int ElementType;

typedef struct
{
	int row,col;/* 所有元的行下标和列下标 */
	ElementType e;
}Triple;

typedef struct
{
	Triple data[MAXSIZE + 1];/* 三元组表,data[0]未用 */
	int rows,cols,nums;/* 矩阵的行数、列数和非零元个数 */
}TSMatrix;

(2)矩阵的转置运算
一般的矩阵转置运算:

for(int i = 0;i < cols;i++)
    for(int j = 0;j < rows;j++)
    {
      dest[j][i] = source[i][j];
    }

时间复杂度为T(n) = O(m×n)

那么,如何在压缩存储结构下实现矩阵的转置运算呢?
这里有两种算法。
方法一:简单转置算法
描述:N中的第1个非零元是M中第1列的第1个非零元
N中的第2个非零元是M中第1列的第2个非零元或M中第2列的第1个非零元…
为找到M中每一列所有非零元素,需对其三元组表从第1个开始起扫描一遍。
代码:

void CreateSMatrix(TSMatrix *M)/* 三元组压缩存储结构的矩阵的创建 */
{
	int k,p = 1,nums = 0;
	printf("请输入行数列数和非零元个数:");
	scanf("%d %d %d",&M->rows,&M->cols,&M->nums);
	for(int i = 1;i <= M->rows;i++)
		for(int j = 1;j <= M->cols;j++)
		{
			scanf("%d",&k);
			if(k != 0)
			{
				nums++;
				M->data[p].row=i;
				M->data[p].col=j;
				M->data[p++].e=k;
			}
		}
		M->nums=nums;
	printf("矩阵创建成功,如下:\n");
}

void PrintSMatrix(TSMatrix *M)/* 打印压缩存储后的M */
{
	int zero = 0,p = 1;
	for(int i = 1;i <= M->rows;i++)
	{
		for(int j = 1;j <= M->cols;j++)
		{
			if((i == M->data[p].row) && (j == M->data[p].col) && (p <= M->rows * M->cols))
			{
				printf("%-3d",M->data[p++].e);
			}
			else   printf("%-3d",zero);
		}
		printf("\n");/* 一行一行的输出 */
	}
}

void TransposeSMatrix_Simple(TSMatrix *M,TSMatrix *N)/* 简单转置算法 */
{
	N->rows = M->cols;
	N->cols = M->rows;
	N->nums = M->nums;
	if(N->nums)
	{
		int q = 1;
	    for(int col = 1;col <= M->cols;++col)
		{
		    for(int p = 1;p <= M->nums;++p)
			{
			    if(M->data[p].col == col && M->data[p].e != 0)
				{
				    N->data[q].row = M->data[p].col;
				    N->data[q].col = M->data[p].row;
			    	N->data[q].e = M->data[p].e;
					q++;
				}
			}
		}
	}
}

时间复杂度:T(n) = O(M->cols × M->nums)
numsM->rows× M->rcols同数量级,
T(n) = O(M->cols^2 × M->rows)
所以,改算法仅适用于 nums 远小于 M->rows× M->rcols
方法二:快速转置算法
描述:N中的第1个非零元是M中第1列的第1个非零元
N中的第2个非零元是M中第1列的第2个非零元或M中第2列的第1个非零元…
为找到M中每一列所有非零元素,需对其三元组表从第1个开始起扫描一遍。
代码:

void TransposeSMatrix_Fast(TSMatrix *M,TSMatrix *N)/* 快速转置算法 */
{
	N->rows = M->cols;
	N->cols = M->rows;
	N->nums = M->nums;
	int num[MAXSIZE],pos[MAXSIZE],q = 1,col;
	for(col = 1;col <= M->cols;col++) num[col] = 0;
	for(int t = 1;t <= N->nums;t++)   ++num[N->data[t].col];/* 求N中每一列所含非零元的个数 */
	pos[1] = 1;
	for(col = 2;col <= M->cols;col++) 
		pos[col] = pos[col - 1] + num[col - 1];
	for(int p = 1;p <= N->nums;p++)
	{
		col = M->data[p].col;
		q = pos[col];
		N->data[q].row = M->data[p].col;
		N->data[q].col = M->data[p].row;
		N->data[q].e = M->data[p].e;
		pos[col]++;
	}
}

时间复杂度为:T(n) = O(M->cols + M->nums)
numsM->rows× M->rcols同数量级,
T(n) = O(M->cols × M->rows)
和非压缩矩阵的转置算法的时间复杂度相同

  • 要注意,我这里的函数参数用的都是指针类型,便于传参,也可以让M作为形参,N作为实参。
    可能表述有误,还望及时指正。这是个人学习的一点总结,辛苦你们看了。
  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值