稀疏矩阵的处理(c语言)

这道题是真的折磨我太久了,之前有个测试用例一直没过,因为要考四级,就一直没有看,今天刚考完四级,体验感不错,明年还来(寄),今晚找那个问题,发现主要是矩阵乘法上面有点小问题,换了个思路,总算解决了,代码可能不够简洁,主要是在输出上比较繁琐,参考就可以,题挺恶心的,特别是对格式的要求等等在这里插入图片描述

题目:

特殊矩阵在采用二维数组存储时,尽管矩阵操作的算法都很简单,但是其空间的利用率很低。 稀疏矩阵就是一种应用很广泛的特殊的矩阵。通常稀疏矩阵在处理时都采用“压缩”存储,即把稀疏矩阵的非零元素抽象成为一个以三元组(行,列,值)为数据元素的线性表来处理,此线性表可以采用顺序存储,也可以采用链式存储。现要求编程实现稀疏矩阵在“压缩”存储时的常用操作,如输出、转置、求和、乘等。

现要求编程实现稀疏矩阵在“压缩”存储时的矩阵的常用操作,如输出、转置、求和、乘等。 即输入两个矩阵,完成如下操作:
(1) 转置。对第一个矩阵进行转置并输出,前面输出标题 “The transformed matrix is:”
(2) 矩阵加。如两个矩阵可以相加,进行两个矩阵的加运算并输出,前面输出标题 “The added matrix is:”;如果不能相加,则输出 “Can not add!”;
(3) 矩阵乘。如果两个矩阵可以相乘,进行两个矩阵的乘并输出,前面输出标题 “The product matrix is:”; 如果不能相乘,则输出 “Can not multiply!”

输入格式:

输入有多行,第1行包括三个整数,分别是矩阵的大小m,n及非零元素的个数r。后面r行分别输入各个非零元素的 行、列、值。

输出格式:

输出有两种形式,操作时分别用符号“L”、“H”指出输出形式。 L: 以三元组的形式输出,即先输出矩阵的行数、列数和非零元素个数,再按行主序依次输出各个非零元素的行、列和值。各输出项之间空格分隔。 H: 按人们习惯的矩阵格式输出,即输出一个mn的矩阵,是零元素的输出0,非零元素输出元素值。设定每个元素占位宽度为4。(要输出矩阵的行号和列号,并对齐)

输入样例:

输入样例1:

10 8 4 
1 8 1
3 3 2 
3 7 3 
10 1 4 
10 8 2 
2 6 1 
3 7 -3
H 

输入样例2:

100 90 5
1 10 100
50 60 200
50 80 100
60 60 200
99 89 10
100 90 4
1 1 10
50 60 -200
50 80 100
70 70 10
L

输出样例:

输出样例1:

The transformed matrix is:
       1   2   3   4   5   6   7   8   9  10
   1   0   0   0   0   0   0   0   0   0   4
   2   0   0   0   0   0   0   0   0   0   0
   3   0   0   2   0   0   0   0   0   0   0
   4   0   0   0   0   0   0   0   0   0   0
   5   0   0   0   0   0   0   0   0   0   0
   6   0   0   0   0   0   0   0   0   0   0
   7   0   0   3   0   0   0   0   0   0   0
   8   1   0   0   0   0   0   0   0   0   0
The added matrix is:
       1   2   3   4   5   6   7   8
   1   0   0   0   0   0   0   0   1
   2   0   0   0   0   0   1   0   0
   3   0   0   2   0   0   0   0   0
   4   0   0   0   0   0   0   0   0
   5   0   0   0   0   0   0   0   0
   6   0   0   0   0   0   0   0   0
   7   0   0   0   0   0   0   0   0
   8   0   0   0   0   0   0   0   0
   9   0   0   0   0   0   0   0   0
  10   4   0   0   0   0   0   0   0
Can not multiply!

输出样例2:

The transformed matrix is:
Rows=90,Cols=100,r=5
10 1 100
60 50 200
60 60 200
80 50 100
89 99 10
The added matrix is:
Rows=100,Cols=90,r=6
1 1 10
1 10 100
50 80 200
60 60 200
70 70 10
99 89 10
Can not multiply!

再附上一个测试用例:

input:

3 3 7
1 1 3
1 2 2
2 1 2
2 2 3
2 3 2
3 2 2
3 3 3
3 3 7
1 1 1
1 3 3
2 2 2
2 3 4
3 1 3
3 2 4
3 3 3
L

output

The transformed matrix is:
Rows=3,Cols=3,r=7
1 1 3
1 2 2
2 1 2
2 2 3
2 3 2
3 2 2
3 3 3
The added matrix is:
Rows=3,Cols=3,r=9
1 1 4
1 2 2
1 3 3
2 1 2
2 2 5
2 3 6
3 1 3
3 2 6
3 3 6
The product matrix is:
Rows=3,Cols=3,r=9
1 1 3
1 2 4
1 3 17
2 1 8
2 2 14
2 3 24
3 1 9
3 2 16
3 3 17

思路:

用了两个结构体实现稀疏矩阵三元组的存储方式,然后就是分别实现转置、加法和乘法,根据要求输出(变态格式)具体的解析直接加在代码中了

代码:

结构体定义及函数声明

#include<stdio.h>
#include <malloc.h>
typedef int ElemType;
#define MAXSIZE 100
typedef struct {
    
    
	int i, j;       //该非零元的行下标和列下标
	ElemType e;     //数据域
}Triple;
typedef struct {
    
    
	Triple data[MAXSIZE]; 		//非零元三元组表
	int mu, nu, tu;           //矩阵的行数,列数和非零元个数
}TSMatrix;
void GreateSMatrix(TSMatrix* M);	//创建
void TransposeSMatrix(TSMatrix* M, TSMatrix* T);//转置
void PrintzhuanH(TSMatrix* T);//H类型输出转置矩阵
void PrintzhuanL(TSMatrix* T);//L类型输出转置矩阵
void PrintADDL(TSMatrix* T);//L类型输出和矩阵
void PrintADDH(TSMatrix* T);//H类型输出和矩阵
void PrintmultiplyL(TSMatrix* T);//L类型输出乘矩阵
void PrintmultiplyH(TSMatrix* T);//H类型输出乘矩阵
bool ADD(TSMatrix* A, TSMatrix* B, TSMatrix* C);//矩阵加
bool multiply(TSMatrix* A, TSMatrix* B, TSMatrix* C);//矩阵乘

主函数

int main() {
    
    
	char LH2;
	char LH;
	TSMatrix* M = (TSMatrix*)malloc(sizeof(TSMatrix));
	TSMatrix* T = (TSMatrix*)malloc(sizeof(TSMatrix));
	GreateSMatrix(M);
	TransposeSMatrix(M, T);
	TSMatrix* M2 = (TSMatrix*)malloc(sizeof(TSMatrix));

	GreateSMatrix(M2);
	scanf("%c", &LH2);
	LH = getchar();
	TSMatrix* A = (TSMatrix*)malloc(sizeof(TSMatrix));
    A->tu = 0;
    TSMatrix* MU = (TSMatrix*)malloc(sizeof(TSMatrix));

	if (LH == 'L')
	{
    
    
		PrintzhuanL(T);//转置
	}
	else {
    
    
		PrintzhuanH(T);
	}

    if (ADD(M, M2, A)) {
    
    
		if (LH == 'L')
		{
    
    
			PrintADDL(A);
		}
		else {
    
    
			PrintADDH(A);
		}
    }
    else {
    
    
        printf("Can not add!\n");
    }

    if (multiply(M, M2, MU)) {
    
    
		if (LH == 'L') {
    
    
			PrintmultiplyL(MU);
		}
		else {
    
    
			PrintmultiplyH(MU);
		}
    }
    else {
    
    
        printf("Can not multiply!");
    }
	return 0;
}

创建稀疏矩阵

void GreateSMatrix(TSMatrix* M) //创建稀疏矩阵M
{
    
    
	scanf("%d %d %d", &M->mu, &M->nu, &M->tu);
	if ((M->mu) > 0 && (M->nu) > 0) {
    
    
		if (M->tu < MAXSIZE)
		{
    
    
			for (int i = 1; i <= M->tu; i++) {
    
    
				scanf("%d %d %d", &M->data[i].i, &M->data[i].j, &M->data[i].e);
			}
		}
	}
}

求转置矩阵

void TransposeSMatrix(TSMatrix* M, TSMatrix* T)//求稀疏矩阵M的转置矩阵T
{
    
    
	T->mu = M->nu, T->nu = M->mu, T->tu = M->tu;
	if (T->tu) {
    
    
		int q = 0, p, j;
			for (p = 1; p <= M->tu; p++){
    
    
					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;
				}
	}
}

求和矩阵

void EnterTriple(TSMatrix* Q, int row, int col, int e)
{
    
    
    Q->data[Q->tu].i = row;
    Q->data[Q->tu].j = col;
    Q->data[Q->tu].e = e;
    Q->tu++;
}
bool ADD(TSMatrix* A, TSMatrix* B, TSMatrix* C)
{
    
    
    if (A->mu == B->mu && A->nu == B->nu) {
    
    //判断是不是相同形式的矩阵
        C->mu = A->mu; C->nu = A->nu;
        int i = 1, j = 1;
        while (i <= A->tu && j <= B->tu)
        {
    
    
            if (A->data[i].i < B->data[j].i)//判断A的行数是否比B小
            {
    
    
                EnterTriple(C, A->data[i].i, A->data[i].j, A->data[i].e);
                i++;
            }
            else if (A->data[i].i == B->data[j].i)//行数相等判断列数
            {
    
    
                if (A->data[i].j < B->data[j].j)
                {
    
    
                    EnterTriple(C, A->data[i].i, A->data[i].j, A->data[i].e);
                    i++;
                }
                else if (A->data[i].j > B->data[j].j)
                {
    
    
                    EnterTriple(C, B->data[j].i, B->data[j].j, B->data[j].e);
                    j++;
                }
                else
                {
    
    
                    if (B->data[j].e + A->data[i].e != 0)
                        EnterTriple(C, B->data[j].i, B->data[j].j, B->data[j].e + A->data[i].e);
                    i++;
                    j++;
                }
            }
            else
            {
    
    
                EnterTriple(C, B->data[j].i, B->data[j].j, B->data[j].e);
                j++;
            }
        }
        while (i <= A->tu)
        {
    
    
            EnterTriple(C, A->data[i].i, A->data[i].j, A->data[i].e);
            i++;
        }
        while (j <= B->tu)
        {
    
    
            EnterTriple(C, B->data[j].i, B->data[j].j, B->data[j].e);
            j++;
        }
        return true;
    }
    else {
    
    
        return false;
    }
}

求乘法矩阵

附上i,j,k三个参数的遍历方式图
在这里插入图片描述

bool multiply(TSMatrix* A, TSMatrix* B, TSMatrix* C)//矩阵相乘
{
    
    
	if (A->nu != B->mu)                                    //前矩阵列数要等于后矩阵行数
		return false;
	C->mu = A->mu;                                         //结果矩阵的行数为前矩阵行数
	C->nu = B->nu;	
	C->tu = 0;
	int p, q, x, cnt;
	int i1, j1;
	int sum;
	cnt = 0;
	for (int i = 1; i <= A->mu; i++)
	{
    
    

		for (int j = 1; j <= B->nu; j++)//遍历每行每列
		{
    
    
			sum = 0;
			for (int k = 1; k <= A->nu; k++)//每个行与每个列单个数的遍历
			{
    
    
				p = 0; q = 0;
				for (i1 = 0; i1 <= A->tu; i1++) {
    
      //遍历A找符合i行k列的数
					if (A->data[i1].i == i && A->data[i1].j == k) p = A->data[i1].e;
				}
				for (j1 = 0; j1 <= B->tu; j1++) {
    
    //遍历B找符合k行j列的数
					if (B->data[j1].i == k && B->data[j1].j == j) q = B->data[j1].e;
				}
				sum = sum + (p * q);
			}
			if (sum != 0) {
    
    
				C->data[cnt].e = sum;
				C->data[cnt].i = i;
				C->data[cnt].j = j;
				cnt++;
			}

		}
	}
	C->tu = cnt;
	return true;
}

输出函数

有6个输出函数,分别对应转置,和矩阵,乘法矩阵的H和L两种输出模式

  1. 在三元组的输出模式下,需要进行行主序的排序,用了个比较简单的冒泡排序
  2. 在矩阵表的输出模式下对空格的要求很严格,最多占位宽度为4,所以可能的数字有7种情况,正数的1、2、3、4位数和负数的1、2、3位数(负号是一个占位宽度)(例:1、10、100、1000、-1、-10、-100)其实这里可以简化,就交给你们了在这里插入图片描述
void PrintzhuanL(TSMatrix* T) //输出矩阵
{
    
    
	TSMatrix* zhong = (TSMatrix*)malloc(sizeof(TSMatrix));
	TSMatrix* te = (TSMatrix*)malloc(sizeof(TSMatrix));
	printf("The transformed matrix is:\n");
	printf("Rows=%d,Cols=%d,r=%d\n", T->mu, T->nu, T->tu);
	//冒泡排序
	for (int i = 1; i < T->tu; i++) {
    
    
		for (int j = 1; j < T->tu; j++) {
    
    
			if (T->data[i].i < T->data[j].i) {
    
    
				zhong->data[0] = T->data[i];
				T->data[i] = T->data[j];
				T->data[j] = zhong->data[0];
			}
			else if (T->data[i].i == T->data[j].i) {
    
    
				if (T->data[i].j < T->data[j].j) {
    
    
					te->data[0] = T->data[i];
					T->data[i] = T->data[j];
					T->data[j] = te->data[0];
				}
			}
		}
	}
	for (int i = 0; i < T->tu; i++) {
    
    
		printf("%d %d %d", T->data[i].i, T->data[i].j, T->data[i].e);
		printf("\n");
	}
}
void PrintzhuanH(TSMatrix* T) {
    
    
	printf("The transformed matrix is:\n");
	int** data = (int**)malloc(sizeof(int*) * 100);
	for (int i = 0; i < 100; ++i)
	{
    
    
		data[i] = (int*)malloc(sizeof(int) * 100);
	}
	int cnt = 1;
	for (int i = 0; i <= T->mu; i++) {
    
    
		for (int j = 0; j <= T->nu; j++) {
    
    
			data[i][j] = 0;
		}
	}
	for (int i = 0; i < T->tu; i++) {
    
    	//在指定位置存放非0元,其余位置都为0
		data[T->data[i].i][T->data[i].j] = T->data[i].e;
	}
	printf("    ");
	for (int i = 1; i <= T->nu; i++) {
    
    
		if (i < 10) {
    
    
			printf("   %d", i);
		}
		else if (i < 100) {
    
    
			printf("  %d", i);
		}
		else if (i < 1000) {
    
    
			printf(" %d", i);
		}
	}
	printf("\n");
	for (int i = 1; i <= T->mu; i++) {
    
    
		for (int j = 0; j <= T->nu; j++) {
    
    
			if (j == 0) {
    
    
				if (cnt < 10) {
    
    
					printf("   %d", cnt);
				}
				else if (cnt < 100) {
    
    
					printf("  %d", cnt);
				}
				else if (cnt < 1000) {
    
    
					printf("  %d", cnt);
				}
				cnt++;
			}
			else {
    
    
				if (data[i][j] >= 0) {
    
    
					if (data[i][j] < 10) {
    
    
						printf("   %d", data[i][j]);
					}
					else if (data[i][j] < 100) {
    
    
						printf("  %d", data[i][j]);
					}
					else if (data[i][j] < 1000) {
    
    
						printf(" %d", data[i][j]);
					}
				}
				else {
    
    
					if (data[i][j] > -10) {
    
    
						printf("  %d", data[i][j]);
					}
					else if (data[i][j] >-100) {
    
    
						printf(" %d", data[i][j]);
					}
					else if (data[i][j] >-1000) {
    
    
						printf("%d", data[i][j]);
					}
				}
			}
		}
		printf("\n");
	}
}
void PrintADDL(TSMatrix* T) //输出和矩阵
{
    
    
    printf("The added matrix is:\n");
    printf("Rows=%d,Cols=%d,r=%d\n", T->mu, T->nu, T->tu);
	TSMatrix* zhong1 = (TSMatrix*)malloc(sizeof(TSMatrix));
	TSMatrix* te1 = (TSMatrix*)malloc(sizeof(TSMatrix));
		//冒泡排序
	for (int i = 1; i < T->tu; i++) {
    
    
		for (int j = 1; j < T->tu; j++) {
    
    
			if (T->data[i].i < T->data[j].i) {
    
    
				zhong1->data[0] = T->data[i];
				T->data[i] = T->data[j];
				T->data[j] = zhong1->data[0];
			}
			else if (T->data[i].i == T->data[j].i) {
    
    
				if (T->data[i].j < T->data[j].j) {
    
    
					te1->data[0] = T->data[i];
					T->data[i] = T->data[j];
					T->data[j] = te1->data[0];
				}
			}
		}
	}
    for (int i = 0; i < T->tu; i++) {
    
    
        printf("%d %d %d", T->data[i].i, T->data[i].j, T->data[i].e);
        printf("\n");
    }
}
void PrintADDH(TSMatrix* T) {
    
    
	printf("The added matrix is:\n");
	int** data1 = (int**)malloc(sizeof(int*) * 100);
	for (int i = 0; i < 100; ++i)
	{
    
    
		data1[i] = (int*)malloc(sizeof(int) * 100);
	}
	int cnt = 1;
	for (int i = 0; i <= T->mu; i++) {
    
    
		for (int j = 0; j <= T->nu; j++) {
    
    
			data1[i][j] = 0;
		}
	}
	for (int i = 0; i < T->tu; i++) {
    
    	//在指定位置存放非0元,其余位置都为0
		data1[T->data[i].i][T->data[i].j] = T->data[i].e;
	}
	printf("    ");
	for (int i = 1; i <= T->nu; i++) {
    
    
		if (i < 10) {
    
    
			printf("   %d", i);
		}
		else if (i < 100) {
    
    
			printf("  %d",i);
		}
		else if (i < 1000) {
    
    
			printf(" %d",i);
		}
	}
	printf("\n");
	for (int i = 1; i <= T->mu; i++) {
    
    
		for (int j = 0; j <= T->nu; j++) {
    
    
			if (j == 0) {
    
    
				if (cnt < 10) {
    
    
					printf("   %d", cnt);
				}
				else if (cnt < 100) {
    
    
					printf("  %d", cnt);
				}
				else if (cnt < 1000) {
    
    
					printf("  %d", cnt);
				}
				cnt++;
			}
			else {
    
    
				if (data1[i][j] >= 0) {
    
    
					if (data1[i][j] < 10) {
    
    
						printf("   %d", data1[i][j]);
					}
					else if (data1[i][j] < 100) {
    
    
						printf("  %d", data1[i][j]);
					}
					else if (data1[i][j] < 1000) {
    
    
						printf(" %d", data1[i][j]);
					}
				}
				else {
    
    
					if (data1[i][j] > -10) {
    
    
						printf("  %d", data1[i][j]);
					}
					else if (data1[i][j] > -100) {
    
    
						printf(" %d", data1[i][j]);
					}
					else if (data1[i][j] > -1000) {
    
    
						printf("%d", data1[i][j]);
					}
				}
			}
		}
		printf("\n");
	}
}
void PrintmultiplyL(TSMatrix* T) {
    
    
	printf("The product matrix is:\n");
	printf("Rows=%d,Cols=%d,r=%d\n", T->mu, T->nu, T->tu);
	TSMatrix* zhong2 = (TSMatrix*)malloc(sizeof(TSMatrix));
	TSMatrix* te2 = (TSMatrix*)malloc(sizeof(TSMatrix));
		//冒泡排序
	for (int i = 1; i < T->tu; i++) {
    
    
		for (int j = 1; j < T->tu; j++) {
    
    
			if (T->data[i].i < T->data[j].i) {
    
    
				zhong2->data[0] = T->data[i];
				T->data[i] = T->data[j];
				T->data[j] = zhong2->data[0];
			}
			else if (T->data[i].i == T->data[j].i) {
    
    
				if (T->data[i].j < T->data[j].j) {
    
    
					te2->data[0] = T->data[i];
					T->data[i] = T->data[j];
					T->data[j] = te2->data[0];
				}
			}
		}
	}
	for (int i = 0; i < T->tu; i++) {
    
    
		printf("%d %d %d", T->data[i].i, T->data[i].j, T->data[i].e);
		printf("\n");
	}
}
void PrintmultiplyH(TSMatrix* T) {
    
    
	printf("The product matrix is:\n");
	int** data2 = (int**)malloc(sizeof(int*) * 100);
	for (int i = 0; i < 100; ++i)
	{
    
    
		data2[i] = (int*)malloc(sizeof(int) * 100);
	}
	int cnt = 1;
	for (int i = 0; i <= T->mu; i++) {
    
    
		for (int j = 0; j <= T->nu; j++) {
    
    
			data2[i][j] = 0;
		}
	}
	for (int i = 0; i < T->tu; i++) {
    
    	//在指定位置存放非0元,其余位置都为0
		data2[T->data[i].i][T->data[i].j] = T->data[i].e;
	}
	printf("    ");
	for (int i = 1; i <= T->nu; i++) {
    
    
		if (i < 10) {
    
    
			printf("   %d", i);
		}
		else if (i < 100) {
    
    
			printf("  %d", i);
		}
		else if (i < 1000) {
    
    
			printf(" %d", i);
		}
	}
	printf("\n");
	for (int i = 1; i <= T->mu; i++) {
    
    
		for (int j = 0; j <= T->nu; j++) {
    
    
			if (j == 0) {
    
    
				if (cnt < 10) {
    
    
					printf("   %d", cnt);
				}
				else if (cnt < 100) {
    
    
					printf("  %d", cnt);
				}
				else if (cnt < 1000) {
    
    
					printf("  %d", cnt);
				}
				cnt++;
			}
			else {
    
    
				if (data2[i][j] >= 0) {
    
    
					if (data2[i][j] < 10) {
    
    
						printf("   %d", data2[i][j]);
					}
					else if (data2[i][j] < 100) {
    
    
						printf("  %d", data2[i][j]);
					}
					else if (data2[i][j] < 1000) {
    
    
						printf(" %d", data2[i][j]);
					}
					else  {
    
    
						printf("%d", data2[i][j]);
					}
				}
				else {
    
    
					if (data2[i][j] > -10) {
    
    
						printf("  %d", data2[i][j]);
					}
					else if (data2[i][j] > -100) {
    
    
						printf(" %d", data2[i][j]);
					}
					else if (data2[i][j] > -1000) {
    
    
						printf("%d", data2[i][j]);
					}
				}
			}
		}
		printf("\n");
	}
}

提交结果:

在这里插入图片描述
代码比较粗糙,可以优化的地方很多,各位大佬可以尽情指点
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_52118067/article/details/121942965
今日推荐