C语言实现稀硫矩阵的三元组表示及其转置

完整代码请参考GitHub:https://github.com/jie12366/spmatrix.git
由于稀硫矩阵中的零元素个数很多,按一般的矩阵存储方法必然会很浪费空间,为了节省空间,通常用压缩储存的方法来只存储稀硫矩阵的非零元素。这里介绍最常用的三元组表示法。
三元组表示的形式如下:(其中i表示非零元素所在的行,j表示非零元素所在的列,value表示非零元素的值)

	(i,j,valueL)

例如这里有个A7*6的稀硫矩阵:

	|0	0	-5	0	1	0|
	|0	0	0	2	0	0|
	|3	0	0	0	0	0|
   A	|0	0	0	0	0	0|
	|12	0	0	0	0	0|
	|0	0	0	0	0	4|
	|0	0	21	0	0	0|

其对应的三元组表示如下:

	    B	 |	0	1	2
	——————————————————————————————————
	    0    |	7	6	7
	    1	 |	0	2	-5
	    2	 |	0	4	1
	    3	 |	1	3	2
	    4	 |	2	0	3
	    5	 |	4	0	12
	    6	 |	5	5	4
	    7    |	6	2	21

矩阵B的第一行分别是稀硫矩阵A的行数,列数和非零元素的个数,并且三元组是按行号递增排序的,行号相同的按列号递增排序。
稀硫矩阵A及其对应的三元组表示矩阵B的数据类型如下:

/*稀硫矩阵的头文件*/

typedef struct {
	int data[100][100];    //存放稀硫矩阵的二维数组
	int m,n;               //分别存放稀硫矩阵的行数和列数 
}matrix;

typedef int spmatrix[100][3]; //稀硫矩阵对应的三元组 

那么下面我们来实现如何将一个稀硫矩阵转换为对应的三元组表示。因为稀硫矩阵的三元组表示是按照行优先排序的,故我们必须按顺序逐行扫描,并把非零元素写入三元组表示的数组中。具体实现过程如下:

/*将稀硫矩阵转换为三元组表示 */
void compressMatrix(matrix A,spmatrix B){
	int i,j;
	int x = 1;
	/*按行优先扫描整个稀硫矩阵*/
	for(i = 0;i<A.m;i++){
		for(j= 0;j<A.n;j++){
		/*如果元素非零,则写入三元组表示的数组中*/
			if(text[i][j] != 0){
				B[x][0] = i;   //对应的行号
				B[x][1] = j;   //对应的列号
				B[x][2] = A.data[i][j];//非零元素的值
				x++;
			}
		}
	}
	/*三元组的第一行分别是稀硫矩阵的行数,列数,非零元素个数*/
	B[0][0] = A.m;  //行数
	B[0][1] = A.n;  //列数
	B[0][2] = x-1;  //非零元素的个数
}

求稀硫矩阵的转置是最常用的算法之一,下面我们来看看在三元组表示下如何实现稀硫矩阵的转置。
这里有个问题:我们要做到转置后非零元素的排列仍然按照行优先的顺序,必须保证每个非零元素在交换行号和列号后能立即确定其在转置矩阵C中的最终位置。
解决方法:首先确定B中的每一列的非零元素的个数,也就是转置后C中每一行非零元素的个数,从而可以计算出C中每一行的非零元素的起始位置。
C中每一行非零元素的起始位置=上一行非零元素的起始位置+上一行非零元素的个数。
具体实现算法及代码解析如下:

/*在三元组表示下实现稀硫矩阵的转置 */
void tranSpmatrix(spmatrix b,spmatrix c){
	int i,j,t,m,n;
	int x[100];    //该数组用来存放b中每一列非零元素的个数
	int y[100];    //该数组用来存放c中每一行非零元素的个数
	m = b[0][0]; n = b[0][1]; t =b[0][2];
	/*获取稀硫矩阵的行数,列数及非零元素的个数*/
	c[0][0] = m; c[0][1] = n; c[0][2] = t;  
	/*如果非零元素个数大于0*/
	if(t>0){
		for(i=0;i<n;i++) x[i] = 0;   //初始化数组元素为0
		/*统计b中每一列非零元素的个数 */
		for(i=1;i<=t;i++){
			x[b[i][1]] = x[b[i][1]] + 1;
		} 
		/*求矩阵c中每一行非零元素三元组的起始位置 */
		y[0] = 1;   //初始化为1,实际从第二行开始放非零元素
		for(i=1;i<n;i++){
		/*该行位置=上一行位置+上一行非零元素个数*/
			y[i] = y[i-1] + x[i-1];   
		}
		for(i=1;i<=t;i++){
			j = y[b[i][1]];    //令数组下标等于该行的起始位置,b[i][1]是在稀硫矩阵中的实际列号,也就是转置后的行号
			/*交换行列写入最终位置*/
			c[j][0] = b[i][1];
			c[j][1] = b[i][0];
			c[j][2] = b[i][2];
			y[b[i][1]] = j+1;  //如果该行非零元素不止一个,那么该行位置+1,用于把该行元素存在三元组的下一行。
		}
	} 
}

测试运行结果如下:
在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
稀疏矩阵三元组转置可以通过以下步骤实现: 1. 定义稀疏矩阵三元组结构体,包括行数、列数、非零元素个数和三个数组:行下标数组、列下标数组和值数组。 2. 从键盘输入稀疏矩阵的元素,利用三元组表进行存储,并从屏幕显示稀疏矩阵的元素。 3. 定义一个新的三元组结构体,用于存储转置后的稀疏矩阵。 4. 遍历原始稀疏矩阵的每一个非零元素,将其转置到新的三元组结构体中。 5. 从屏幕显示转置后的稀疏矩阵的元素。 下面是一个简单的C语言实现稀疏矩阵三元组转置的代码示例: ``` #include <stdio.h> #define MAX_SIZE 100 typedef struct { int row; int col; int val; } Triple; typedef struct { int row; int col; int num; Triple data[MAX_SIZE]; } Matrix; void transpose(Matrix *a, Matrix *b) { int num[MAX_SIZE], pos[MAX_SIZE]; int i, j, k; b->row = a->col; b->col = a->row; b->num = a->num; if (b->num > 0) { for (i = 0; i < a->col; i++) { num[i] = 0; } for (k = 0; k < a->num; k++) { i = a->data[k].col; num[i]++; } pos[0] = 0; for (i = 1; i < a->col; i++) { pos[i] = pos[i - 1] + num[i - 1]; } for (k = 0; k < a->num; k++) { i = a->data[k].col; j = pos[i]; b->data[j].row = a->data[k].col; b->data[j].col = a->data[k].row; b->data[j].val = a->data[k].val; pos[i]++; } } } int main() { Matrix a, b; int i, j; printf("请输入稀疏矩阵的行数、列数和非零元素个数:\n"); scanf("%d%d%d", &a.row, &a.col, &a.num); printf("请输入稀疏矩阵的元素:\n"); for (i = 0; i < a.num; i++) { scanf("%d%d%d", &a.data[i].row, &a.data[i].col, &a.data[i].val); } printf("稀疏矩阵三元组表示为:\n"); for (i = 0; i < a.num; i++) { printf("%d %d %d\n", a.data[i].row, a.data[i].col, a.data[i].val); } transpose(&a, &b); printf("转置后的稀疏矩阵三元组表示为:\n"); for (i = 0; i < b.num; i++) { printf("%d %d %d\n", b.data[i].row, b.data[i].col, b.data[i].val); } return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值