使用C语言实现矩阵转置(稀疏矩阵)

目录

1.转置矩阵(普通矩阵)

2.转置矩阵(稀疏矩阵)

(1)稀疏矩阵

(2)稀疏矩阵的压缩存储方式

(3)理论运算方法


1.转置矩阵(普通矩阵)

矩阵的转置:根据主对角元素作为对称轴进行元素的互换。转置运算是一种最简单的矩阵运算。对一个mxn的矩阵M进行转置得到矩阵T(nxm),且T(i,j)=M(j,i),1<=i<=n,1<=j<=m.

注:虽然矩阵的转置非常的简单,但是对于其在计算机上的时间复杂度也是做了很多的优化,特别是对稀疏矩阵的转置,因为稀疏矩阵的存储方式不是直接使用nxn的方式进行存储的,而是采用其他的方式:如三元组等。

#include<stdlib.h>
#include<stdio.h>

#define Mat_n 5

typedef int ElemType;

int M[Mat_n][Mat_n];
//矩阵的转置
void TransposeMatrix(int N[Mat_n][Mat_n],int n,int m){
	for(int col=1;col<=m;col++){
		for(int row=1;row<=n;row++){
			M[col][row]=N[row][col];
		}
	}
} 


int main(){
	int n,m; 
	int N[Mat_n][Mat_n];
	printf("请输入矩阵(方阵)行和列: ");
	scanf("%d %d",&n,&m);
	//初始化
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			N[i][j]=M[i][j]=0; 
		}
	}
	printf("请输入矩阵(方阵):\n");
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&N[i][j]); 
		}
	}
	TransposeMatrix(N,n,m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			printf("%d  ",M[i][j]);
		}
		printf("\n");
	}
	return 0;
}

/*
4 4
1  2  0  3
5  6  3  8
12 23 45 67
9  5  3  5
*/

2.转置矩阵(稀疏矩阵)

(1)稀疏矩阵

(2)稀疏矩阵的压缩存储方式

由于是稀疏矩阵,所以只需要存储非零元即可,非零元的位置为(i,j),所以采用三元组的形式(i,j,aij)唯一确定矩阵A的非零元。

比如:((1,2,2),(1,3,9),(3,1,3),(3,6,4),(4,3,2),(5,2,8),(6,1,5),(6,4,7))

(3)理论运算方法

假设M矩阵的三元组形式如下:

M.data

元素

1

2

12

1

3

9

3

1

-3

3

6

14

4

3

24

5

2

18

6

1

15

6

1

-7

转置之后的T矩阵三元组如下:

T.data

元素

1

3

-1

1

6

15

2

1

12

2

5

18

2

1

9

2

4

24

4

6

-7

6

3

14

步骤:

      第一步:将矩阵的行列值进行互换;

      第二步:将每个元组中的i和j值进行调换;

      第三步:重排三元组之间的次序即可实现矩阵的转置;

而对于第三步的具体实现步骤:

      方法一:

按照T.data中的三元组的次序依次在M.data中找到相应的三元组进行转置。也就是说对其M.data中的三元组表进行扫描一遍(从第一行到最后一行),由于M.data是以行序为主序来存放每个非零元的,所以也可以得到T.data应有的次序。

#include<stdlib.h>
#include<stdio.h>

#define MAXSIZE 10

typedef int ElemType;

typedef struct {
	int i,j;
	ElemType e;
}Triple;

typedef struct {
	Triple data[MAXSIZE];
	int mu,nu,tu;//矩阵的行,列和非零元个数 
}TSMatrix; 

void TransposeSMatrix(TSMatrix M,TSMatrix&T){
	//矩阵的行列互换 
	T.mu=M.nu;
	T.nu=M.mu;
	T.tu=M.tu;
	if(T.tu){
		int q=1;
		for(int col=1;col<=M.nu;col++){
			for(int p=1;p<=M.tu;p++){
				if(M.data[p].j==col){
					T.data[q].i=M.data[p].j;
					T.data[q].j=M.data[p].i;
					T.data[q].e=M.data[p].e;
					q++;
				}
			}
		}
	}
}


int main(){
	TSMatrix M,T;
	printf("请输入矩阵的行,列和非零元数: \n");
	scanf("%d %d %d",&M.mu,&M.nu,&M.tu);
	printf("请输入矩阵(三元组): \n");
	for(int i=1;i<=M.tu;i++){
		scanf("%d %d %d",&M.data[i].i,&M.data[i].j,&M.data[i].e);
	}
	printf("----------------------------------------------\n");
	TransposeSMatrix(M,T);
	printf("转置矩阵T: \n");
	for(int i=1;i<=T.tu;i++){
		printf("%d %d %d\n",T.data[i].i,T.data[i].j,T.data[i].e);
	}
	return 0;
}
/*
6 6 8

1 2 12 
1 3 9
3 1 -3
3 6 14
4 3  24
5 2 18
6 1 15
6 4 -7
*/




 注:但是方法一从时间复杂度上来说:O(nu x tu),所以和非零元的个数是成正比的;普通的矩阵的转置时间复杂度为O(mu x nu);但是对于方法一来说,当tu的数量级和nu x mu相同时,就会出现时间复杂度为O(mu x nu x nu),所以这个时候比普通的方法还要耗时。因此方法二对其进行了改进。

方法二:

假设:如果能够预先确定矩阵M中的每一列(也就是转置之后的矩阵中的每一行)的第一个非零元在T.data中的应有位置,那么在对M.data中的三元组依次做转置时,便可直接放到T.data中恰当的位置。

为了提前确定位置,首先需要设置两个数组变量:num和cpot。

其中num[col]表示矩阵M中的第col列中非零元的个数,cpot[col]表示M中第col列的第一个非零元在T.data中的恰当位置。

矩阵M的数组cpot的值
col1234567
num[co]2221010
cpot[col]1357889

num[co]更加形象的计算方式:

#include<stdlib.h>
#include<stdio.h>

#define MAXSIZE 10

const int maxn=100;

typedef int ElemType;

typedef struct {
	int i,j;
	ElemType e;
}Triple;

typedef struct {
	Triple data[MAXSIZE];
	int mu,nu,tu;//矩阵的行,列和非零元个数 
}TSMatrix; 


void TransposeSMatrix_1(TSMatrix M,TSMatrix&T){
		//矩阵的行列互换 
	T.mu=M.nu;
	T.nu=M.mu;
	T.tu=M.tu;
	int num[100];
	int cpot[100];
	if(T.tu){
        //初始化
		for(int col=1;col<=M.nu;col++){
			num[col]=0;
		}
		for(int t=1;t<=M.tu;t++){
			++num[M.data[t].j];
		}
		cpot[1]=1;
		for(int col=2;col<=M.nu;col++){
			cpot[col]=cpot[col-1]+num[col-1];
		}
		for(int p=1;p<=M.tu;p++){
			int col=M.data[p].j;
            //提前得到在T.data中第q行
			int q=cpot[col];
			T.data[q].i=M.data[p].j;
			T.data[q].j=M.data[p].i;
			T.data[q].e=M.data[p].e;
            //这里之所以要加就是因为一行有多个元素
			++cpot[col];
		}
	}
}


int main(){
	TSMatrix M,T;
	printf("请输入矩阵的行,列和非零元数: \n");
	scanf("%d %d %d",&M.mu,&M.nu,&M.tu);
	printf("请输入矩阵(三元组): \n");
	for(int i=1;i<=M.tu;i++){
		scanf("%d %d %d",&M.data[i].i,&M.data[i].j,&M.data[i].e);
	}
	printf("----------------------------------------------\n");
	TransposeSMatrix_1(M,T);
	printf("转置矩阵T: \n");
	for(int i=1;i<=T.tu;i++){
		printf("%d %d %d\n",T.data[i].i,T.data[i].j,T.data[i].e);
	}
	return 0;
}
/*
6 6 8

1 2 12 
1 3 9
3 1 -3
3 6 14
4 3  24
5 2 18
6 1 15
6 4 -7
*/




注:方法二比之前多用了两个辅助的数组空间num和cpot,但是从时间上来看的话,时间复杂度为O(nu+tu),如果tu的数量级和nu x mu同等,时间复杂度为O(nu x mu).

 参考书籍《数据结构》(清华大学版)

  • 20
    点赞
  • 140
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
稀疏矩阵转置是指将一个稀疏矩阵按照行列互换的方式变换成另一个稀疏矩阵。下面是一个使用 C 语言实现稀疏矩阵转置的代码示例: ```c #include <stdio.h> #define MAX_TERMS 101 #define MAX_COL 101 typedef struct { int row; int col; int value; } term; void fast_transpose(term a[], term b[]); int main() { term a[MAX_TERMS], b[MAX_TERMS]; int m, n, num_terms; printf("Enter the number of rows and columns in the matrix: "); scanf("%d %d", &m, &n); printf("Enter the number of non-zero elements in the matrix: "); scanf("%d", &num_terms); printf("Enter the non-zero elements of the matrix:\n"); for (int i = 0; i < num_terms; i++) { scanf("%d %d %d", &a[i].row, &a[i].col, &a[i].value); } fast_transpose(a, b); printf("The original matrix is:\n"); for (int i = 0; i < num_terms; i++) { printf("%d %d %d\n", a[i].row, a[i].col, a[i].value); } printf("The transpose matrix is:\n"); for (int i = 0; i < num_terms; i++) { printf("%d %d %d\n", b[i].row, b[i].col, b[i].value); } return 0; } void fast_transpose(term a[], term b[]) { int row_terms[MAX_COL]; int starting_pos[MAX_COL]; int num_cols = a[0].col; int num_terms = a[0].value; b[0].row = num_cols; b[0].col = a[0].row; b[0].value = num_terms; if (num_terms > 0) { for (int i = 0; i < num_cols; i++) { row_terms[i] = 0; } for (int i = 1; i <= num_terms; i++) { row_terms[a[i].col]++; } starting_pos[0] = 1; for (int i = 1; i < num_cols; i++) { starting_pos[i] = starting_pos[i-1] + row_terms[i-1]; } for (int i = 1; i <= num_terms; i++) { int j = starting_pos[a[i].col]++; b[j].row = a[i].col; b[j].col = a[i].row; b[j].value = a[i].value; } } } ``` 该程序通过定义 `term` 结构体来存储稀疏矩阵的非零元素,使用 `fast_transpose` 函数来实现稀疏矩阵转置,通过读取用户输入的行数、列数和非零元素的数量,将原始稀疏矩阵存储在 `a` 数组中,并将转置后的稀疏矩阵存储在 `b` 数组中,最后输出原始矩阵转置后的矩阵

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值