这道题是真的折磨我太久了,之前有个测试用例一直没过,发现主要是矩阵乘法上面有点小问题,换了个思路,总算解决了,代码可能不够简洁,主要是在输出上比较繁琐,参考就可以,题挺恶心的,特别是对格式的要求等等
题目:
特殊矩阵在采用二维数组存储时,尽管矩阵操作的算法都很简单,但是其空间的利用率很低。 稀疏矩阵就是一种应用很广泛的特殊的矩阵。通常稀疏矩阵在处理时都采用“压缩”存储,即把稀疏矩阵的非零元素抽象成为一个以三元组(行,列,值)为数据元素的线性表来处理,此线性表可以采用顺序存储,也可以采用链式存储。现要求编程实现稀疏矩阵在“压缩”存储时的常用操作,如输出、转置、求和、乘等。
现要求编程实现稀疏矩阵在“压缩”存储时的矩阵的常用操作,如输出、转置、求和、乘等。 即输入两个矩阵,完成如下操作:
(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两种输出模式
- 在三元组的输出模式下,需要进行行主序的排序,用了个比较简单的冒泡排序
- 在矩阵表的输出模式下对空格的要求很严格,最多占位宽度为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");
}
}
提交结果:
代码比较粗糙,可以优化的地方很多,各位大佬可以尽情指点