矩阵的压缩存储—用三元组表存储稀疏矩阵

本文深入探讨了特殊矩阵与稀疏矩阵的压缩存储方式,并以三元组表示稀疏矩阵为例,详细介绍了如何进行矩阵转置操作。通过算法分析,对比了稀疏矩阵与普通矩阵在转置过程中的效率差异。最后,提供了一个完整的C程序实例,展示了如何使用稀疏矩阵结构进行矩阵运算。

所谓压缩存储,是指对多个值相同的元素只分配一个空间,对零元素不分配空间。

一、特殊矩阵

特殊矩阵是指值相同的元素分布具有一定规律的矩阵,如对角矩阵、三角矩阵,对称矩阵等,对于此类矩阵,找到一个关系将其元素存储到一维数组中,通过这个关系可以对矩阵中的元素进行随机存取。

二、稀疏矩阵

稀疏矩阵中也含有较多的零元素,但是非零元素的分布没有任何规律,因此在存储非零元素的同时,还必须存储适当的辅助信息,才能迅速确定一个非零元素是矩阵中的哪一个元素。稀疏矩阵的表示有很多种方法,下面仅分析用三元组表示稀疏矩阵存储的方法。
矩阵中非零元素的行号、列号及元素值组成了三元组,三元组按行优先(或列优先)的顺序排列得到一个其结点均是三元组的线性表,此外,要唯一的确定一个稀疏矩阵,还必须确定矩阵的行数和列数,为了方便,还要将非零元素个数存储起来,于是得到稀疏矩阵的一种类型如下:

#define MAX 12
typedef int datatype;
typedef struct 
{
	int i, j;          //行号、列号
	datatype  v;       //元素值
} node;
typedef struct
{
	int m, n, t;  //行数,列数,非零元素个数
	node data[MAX];     //三元组表
}spmatrix;

三、算法分析举例

下面以矩阵的转置简单说明一下如何用稀疏矩阵进行矩阵运算:
将矩阵A转置为B,即B[i][j] = A[j][i],这样看来,其实只需将三元组中的i与j 数值交换即可,但是这样做,转置后的矩阵就不会按照行优先或列优先的顺序在线性表中排列了。由于A的列是B的行,因此按A的列顺序进行转置,得到的转置矩阵B必然是按行排列的,具体算法描述如下:

spmatrix *TransMat(spmatrix *a)     //稀疏矩阵的转置
{
	int p, q, bno = 0;
	spmatrix *b;
	b = (spmatrix *)malloc(sizeof(spmatrix)); //为矩阵b分配内存空间
	b->m = a->n;
	b->n = a->m;
	b->t = 0;
	if (a->t == 0)    //若b中元素全为零,则将b返回
		return b;
	for (p = 0; p < a->n; p++)
		for (q = 0; q < a->t; q++)
			if (a->data[q].j == p)
			{
				b->data[bno].i = a->data[q].j;
				b->data[bno].j = a->data[q].i;
				b->data[bno].v = a->data[q].v;
				bno++;
			}
	b->t = bno;
	return b;
}

上述算法有双重循环,若A有n列t个非零元素,则算法复杂度为O(n x t),若用二维矩阵存储,A有m行n列,则算法复杂度为O(n x m),一般t远大于m,因此在此例中,稀疏矩阵转置算法执行时间更长一些。

四、完整程序举例

下面写一个完成的C程序来测试稀疏矩阵三元组结构及转置算法,程序输入为一个3行4列的整数矩阵,输出转置矩阵。

/*  稀疏矩阵的类型说明及转置算法  */
#include<stdio.h>
#include<stdlib.h>
#define MAX 12
typedef int datatype;
typedef struct 
{
	int i, j;          //行号、列号
	datatype  v;       //元素值
} node;
typedef struct
{
	int m, n, t;  //行数,列数,非零元素个数
	node data[MAX];     //三元组表
}spmatrix;

spmatrix *Create();     //创建一个3行4列的稀疏矩阵
spmatrix *TransMat(spmatrix *a);     //稀疏矩阵的转置
void Output(spmatrix *a);      //在屏幕上以行列的形式输出矩阵

int main()
{
	spmatrix *a = Create();
	spmatrix *b = TransMat(a);
	printf("原矩阵:\n");
	Output(a);
	printf("转置矩阵:\n");
	Output(b);
	return 0;
}

spmatrix *Create()     //创建一个3行4列的稀疏矩阵
{
	int m = 3, n = 4, k = 0, t = 0;
	datatype element;
	spmatrix *matrix;
	matrix = (spmatrix *)malloc(sizeof(spmatrix));   //创建一个稀疏矩阵a
	matrix->m = m;
	matrix->n = n;
	printf("输入12个整数:\n");
	while (k < m*n)
	{
		scanf_s("%d", &element);
		if (element != 0)
		{
			matrix->data[t].i = k / n;
			matrix->data[t].j = k % n;
			matrix->data[t].v = element;
			t++;
		}
		k++;
	}
	matrix->t = t;
	return matrix;
}

spmatrix *TransMat(spmatrix *a)     //稀疏矩阵的转置
{
	int p, q, bno = 0;
	spmatrix *b;
	b = (spmatrix *)malloc(sizeof(spmatrix));   //为矩阵b分配内存空间
	b->m = a->n;
	b->n = a->m;
	b->t = 0;
	if (a->t == 0)    //若b中元素全为零,则将b返回
		return b;
	for (p = 0; p < a->n; p++)
		for (q = 0; q < a->t; q++)
			if (a->data[q].j == p)
			{
				b->data[bno].i = a->data[q].j;
				b->data[bno].j = a->data[q].i;
				b->data[bno].v = a->data[q].v;
				bno++;
			}
	b->t = bno;
	return b;
}

void Output(spmatrix *a)
//输入:稀疏矩阵、行数,列数
//输出:在屏幕上以行列的形式输出矩阵
{
	int i = 0, j = 0, k = 0;
	for (i = 0; i < a->m; i++)
	{
		for (j = 0; j < a->n; j++)
		{
			if (i == a->data[k].i && j == a->data[k].j)
			{
				printf("%d ", a->data[k].v);
				k++;
			}
			else
				printf("%d ", 0);
		}
		printf("\n");
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值