题目
假设稀疏矩阵A采用三元组表示,编写一个函数,计算其转置矩阵B,要求B也用三元组表示。
分析
第一种思路是,首先将用三元组表示的稀疏矩阵A转换成稀疏矩阵的形式,然后稀疏矩阵进行转置,转置后再将其用三元组表示。
第二种思路是,根据给定一个稀疏矩阵构造三元组的方法可以知道,三元组内元素是原矩阵按照行优先存储的结果,因此实现三元组存储的转置运算不能简单地将其中各个元素的行下标和列下标互换,正确的算法应该等效于互换三元组中各个元素的行下标与列下标,并将其按照原矩阵列优先的顺序存储。假设原矩阵为A,具体的做法如下:在A中首先找出第1列中的所有元素,它们是转置矩阵第1行的非零元素,并把它们依次放在转置矩阵的三元组数组B中。然后依次找出第2列中的所有元素,把它们依次放在数组B中。按照同样的方法逐列进行,直到找出第n-1列的所有元素,并把它们依次放在数组B中。
代码
第一种思路的代码:
/* 根据给定的稀疏矩阵A(int型)创建三元组存储结构 */
/* A[][MAXSIZE]指的是稀疏矩阵;m指的是稀疏矩阵的行数;n指的是稀疏矩阵的列数;trimat[][3]指的是三元组 */
void createTrimat(int A[][MAXSIZE],int m,int n,int trimat[][3]) {
int k=1;// 计数器,记录三元组的行下标,从1开始,0存储稀疏矩阵的基本信息
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){// 双层嵌套循环,遍历稀疏矩阵的所有元素
if(A[i][j]!=0){
trimat[k][0]=A[i][j];// trimat[k][0]存储稀疏矩阵中非零元素的值
trimat[k][1]=i;// trimat[k][1]存储稀疏矩阵中非零元素的行下标
trimat[k][2]=j;// trimat[k][2]存储稀疏矩阵中非零元素的列下标
k++;// 计数器加1
}
}
}
/* 存储一些稀疏矩阵的基本信息 */
trimat[0][0]=k-1;// 保存矩阵中非零元素的个数
trimat[0][1]=m;// 保存矩阵的行数
trimat[0][2]=n;// 保存矩阵的列数
}
/* 将矩阵M转置成矩阵R */
void transMat(int M[][MAXSIZE],int m,int n,int R[][MAXSIZE]){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
R[i][j]=M[j][i];
}
}
}
/* 将三元组转换成稀疏矩阵 */
int trimatToMat(int A[][3],int mat[][MAXSIZE]){
int m=A[0][1];// 稀疏矩阵的行数
int n=A[0][2];// 稀疏矩阵的列数
int k=1;// 三元组数组的下标,初始为1,因为trimat[0][0-2]保存的是三元组的一些基本信息
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) { // 双层循环遍历稀疏矩阵
if(i==A[k][1]&&j==A[k][2]) { // 如果i和j能够匹配三元组的下标trimat[k][1]和trimat[k][2]
mat[i][j]=A[k][0];
k++;// 继续遍历三元组的元素
} else {
mat[i][j]=0;
}
}
}
}
/* 将A矩阵转置成B矩阵,A、B都是三元组表示的稀疏矩阵 */
void transTrimat(int A[][3],int B[][3]){
int mat[MAXSIZE][MAXSIZE];
trimatToMat(A,mat);// 将三元组转换成稀疏矩阵
int R[MAXSIZE][MAXSIZE];
transMat(mat,A[0][1],A[0][2],R);// 将矩阵mat转置成矩阵R
createTrimat(R,A[0][2],A[0][1],B);
}
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 20
/* 7.题目:有稀疏矩阵A是用三元组表示的,求其转置矩阵B,B也用三元组表示 */
/* 根据给定的稀疏矩阵A(int型)创建三元组存储结构 */
/* A[][MAXSIZE]指的是稀疏矩阵;m指的是稀疏矩阵的行数;n指的是稀疏矩阵的列数;trimat[][3]指的是三元组 */
void createTrimat(int A[][MAXSIZE],int m,int n,int trimat[][3]) {
int k=1;// 计数器,记录三元组的行下标,从1开始,0存储稀疏矩阵的基本信息
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){// 双层嵌套循环,遍历稀疏矩阵的所有元素
if(A[i][j]!=0){
trimat[k][0]=A[i][j];// trimat[k][0]存储稀疏矩阵中非零元素的值
trimat[k][1]=i;// trimat[k][1]存储稀疏矩阵中非零元素的行下标
trimat[k][2]=j;// trimat[k][2]存储稀疏矩阵中非零元素的列下标
k++;// 计数器加1
}
}
}
/* 存储一些稀疏矩阵的基本信息 */
trimat[0][0]=k-1;// 保存矩阵中非零元素的个数
trimat[0][1]=m;// 保存矩阵的行数
trimat[0][2]=n;// 保存矩阵的列数
}
/* 将矩阵M转置成矩阵R */
void transMat(int M[][MAXSIZE],int m,int n,int R[][MAXSIZE]){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
R[i][j]=M[j][i];
}
}
}
/* 将三元组转换成稀疏矩阵 */
int trimatToMat(int A[][3],int mat[][MAXSIZE]){
int m=A[0][1];// 稀疏矩阵的行数
int n=A[0][2];// 稀疏矩阵的列数
int k=1;// 三元组数组的下标,初始为1,因为trimat[0][0-2]保存的是三元组的一些基本信息
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) { // 双层循环遍历稀疏矩阵
if(i==A[k][1]&&j==A[k][2]) { // 如果i和j能够匹配三元组的下标trimat[k][1]和trimat[k][2]
mat[i][j]=A[k][0];
k++;// 继续遍历三元组的元素
} else {
mat[i][j]=0;
}
}
}
}
/* 将A矩阵转置成B矩阵,A、B都是三元组表示的稀疏矩阵 */
void transTrimat(int A[][3],int B[][3]){
int mat[MAXSIZE][MAXSIZE];
trimatToMat(A,mat);// 将三元组转换成稀疏矩阵
int R[MAXSIZE][MAXSIZE];
transMat(mat,A[0][1],A[0][2],R);// 将矩阵mat转置成矩阵R
createTrimat(R,A[0][2],A[0][1],B);
}
/* 打印矩阵 */
/* A[][MAXSIZE]指的是稀疏矩阵;m指的是稀疏矩阵的行数;n指的是稀疏矩阵的列数 */
void printMat(int A[][MAXSIZE],int m,int n){
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
printf("%d\t",A[i][j]);
}
printf("\n");
}
}
/* 根据三元组打印出原来的稀疏矩阵 */
/* trimat[][3]指的是三元组 */
void printTrimat(int trimat[][3]) {
int m=trimat[0][1];// 稀疏矩阵的行数
int n=trimat[0][2];// 稀疏矩阵的列数
int k=1;// 三元组数组的下标,初始为1,因为trimat[0][0-2]保存的是三元组的一些基本信息
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) { // 双层循环遍历稀疏矩阵
if(i==trimat[k][1]&&j==trimat[k][2]) { // 如果i和j能够匹配三元组的下标trimat[k][1]和trimat[k][2]
printf("%d\t",trimat[k][0]);// 如果能够配对则输出三元组的非零元素的值
k++;// 继续遍历三元组的元素
} else {
printf("0\t");// 如果没有匹配则代表该处位置是0
}
}
printf("\n");// 换行
}
}
/* 打印三元组 */
void print(int trimat[][3]){
printf("\n");
for(int k=1;k<=trimat[0][0];k++){
printf("%d\t",trimat[k][0]);
}
printf("\n");
}
int main() {
// 稀疏矩阵
int A[][MAXSIZE]= {
{0,0,0,1},
{0,0,3,2},
{1,0,0,0},
{0,2,0,0},
{1,0,0,0}
};
int m=5,n=4;// 指的是稀疏矩阵的行数和列数
printf("稀疏矩阵:\n");
printMat(A,m,n);// 打印稀疏矩阵
printf("转置后的稀疏矩阵:\n");
int RS[MAXSIZE][MAXSIZE];
transMat(A,m,n,RS);
printMat(RS,n,m);
int trimat[MAXSIZE][3];
createTrimat(A,m,n,trimat);// 根据稀疏矩阵创建三元组
printf("三元组所打印的稀疏矩阵:\n");
printTrimat(trimat);// 根据三元组打印原矩阵
printf("三元组:\n");
print(trimat);// 打印三元组
int R[MAXSIZE][3];
transTrimat(trimat,R);
printf("转置后的三元组:\n");
print(R);// 打印三元组
printf("转换:\n");
int mat[MAXSIZE][MAXSIZE];
trimatToMat(trimat,mat);
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
printf("%d\t",mat[i][j]);
}
printf("\n");
}
return 0;
}
运行结果如下:
第二种思路的代码:
void transpose(int A[][3],int B[][3]) {
int p,q,col;
B[0][0]=A[0][0];// 保存的是A矩阵中的非零元素的个数
B[0][1]=A[0][2];// B[0][1]保存的是B三元组中(即转置后矩阵)的行数,值为原矩阵的列数
B[0][2]=A[0][1];// B[0][2]保存的是B三元组中(即转置后矩阵)的列数,值为原矩阵的行数
if(B[0][0]>0) {
q=1;
for(col=0; col<B[0][1]; col++) { // 按列转置
for(p=1; p<=B[0][0]; p++) {
if(A[p][2]==col) {
B[q][0]=A[p][0];
B[q][1]=A[p][2];
B[q][2]=A[p][1];
q++;
}
}
}
}
}