稀疏矩阵的实现

27 篇文章 1 订阅
3 篇文章 0 订阅
  • 主要实现的难点在于稀疏矩阵的转置以及矩阵乘法。
  • 对用到的数据结构定义不懂的可参考严蔚敏老师的数据结构书籍,这里讲严老师讲的两种数据结构三元组结构行逻辑结构 整合到一起。
  • 稀疏矩阵是线性结构中比较难的一块知识点,不懂的建议去b站看看严老师的视频。
  • 实现环境:linux
数据结构
typedef struct {
	int i, j; //行坐标,列坐标
	Elem e; //元素值
}Triple;//三元组(i,j,e)

typedef struct {
	Triple data[MAXSIZE]; 
	int rpos[MAXRC];
	int *num;
	int *cpot;
	int mu, nu, tu; //总行数,总列数,非零元素总数
}Matrix;
  1. 其中rpos表示每行第一个元素在data中的位置
  2. num表示每一列元素的个数
  3. cpot表示每一列第一个元素在转置矩阵中应处的位置

Matrix.h

#ifndef MATRIX_H_
#define MATRIX_H_

#include <stdbool.h>
#define MAXSIZE 12500
#define MAXRC 500

typedef int Elem;

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

typedef struct {
	Triple data[MAXSIZE];
	int rpos[MAXRC];
	int *num;
	int *cpot;
	int mu, nu, tu;
}Matrix;


/*create a matrix*/
void CreateMatrix(Matrix *M);

/*destroy the matrix*/
void DestroyMatrix(Matrix *M);

/*print the matrix*/
void PrintMatrix(Matrix M);

/*return the matrix transpose of a given matrix*/
bool TransposeMatrix(Matrix M, Matrix *T);

/*take the product of the sparse matrix Q=M*N*/
bool MultiMatrix(Matrix M, Matrix N, Matrix *T);

#endif

Matrix.c

#include "Matrix.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*create a matrix*/
void CreateMatrix(Matrix *M) {
	int m, n, t;
	
	scanf("%d%d%d", &m, &n, &t);
	//scanf("%d", &n);
	//scanf("%d", &t);
	M->mu = m;
	M->nu = n;
	M->tu = t;
	//printf("%d\n", M->tu);
	Triple T;
	bool k;
	int i;
	scanf("%d%d%d", &T.i, &T.j, &T.e);
	do {
		k = 0;
		if (T.i < 1 || T.i > M->mu || T.j < 1 || T.j > M->nu) {
			k = 1;
			printf("wrong input !\nplease enter again! \n");
			scanf("%d%d%d", &T.i, &T.j, &T.e);
		}
	}while(k);
	M->data[0] = T;
//	printf("%d\n",M->data[0].i);
	for (i = 1; i < M->tu; i++) {
		scanf("%d%d%d", &T.i, &T.j, &T.e);
	        do {
        	        k = 0;
               		if (T.i < 1 || T.i > M->mu || T.j < 1 || T.j > M->nu || T.i < M->data[i-1].i || (T.i == M->data[i-1].i && T.j <= M->data[i-1].j)) {
                        	k = 1;
                       		printf("wrong input !\nplease enter again! \n");
                        	scanf("%d%d%d", &T.i, &T.j, &T.e);
                	}
        	}while(k);
        	M->data[i] = T;

	}
	M->num = (int*)malloc(M->nu*sizeof(int));
	M->cpot = (int*)malloc(M->nu*sizeof(int));
	memset(M->num, 0x0, M->nu*sizeof(int));
	memset(M->cpot, 0x0, M->nu*sizeof(int));
	for (i = 0; i < M->tu; i++) {
		M->num[M->data[i].j - 1]++;	
	}
	M->cpot[0] = 1;
	for (i = 1; i < M->nu; i++) {
		M->cpot[i] = M->cpot[i-1] + M->num[i-1];	
	}
	M->rpos[0] = 1;
	int Num[M->mu];
	memset(Num, 0x0, M->mu*sizeof(int));
	for(i = 0; i < M->tu; i++) {
		Num[M->data[i].i-1]++;
	}
	/*for(i = 1 ; i < M->mu ; i++) {
                printf("%d\n",Num[i-1]);
        }*/
	
	for(i = 1 ; i < M->mu ; i++) {
		M->rpos[i] = M->rpos[i-1] + Num[i-1];
	}
	/*for (i = 1; i < M->tu; i++) {
		if (M->data[i].i > M->data[i-1].i) {
			M->rpos[M->data[i].i-1] = i + 1;
		}
	}*/
	/*for (i = 1; i < M->tu; i++) {
		if (M->data[i].i > M->data[i-1].i+1) {
			int m = M->data[i].i - M->data[i-1].i;
			for (int a = M->data[i-1].i + 1; a < M->data[i].i; i++) {
				M->rpos[a-1] = M->rpos[M->data[i-1].i-1];
			}
		}
	}*/
}

/*destroy the matrix*/
void DestroyMatrix(Matrix *M) {
	M->mu = 0;
	M->tu = 0;
	M->nu = 0;
	free(M->num);
	free(M->cpot);			
}

/*print the matrix*/
void PrintMatrix(Matrix M) {
	int i;
 
	printf("%d行%d列%d个非零元素。\n",M.mu,M.nu,M.tu);
 
   	printf("行  列  元素值\n");
 
   	for(i=0;i<M.tu;i++)
 
     		printf("%2d%4d%8d\n",M.data[i].i,M.data[i].j,M.data[i].e);
 
   	for(i=1;i<=M.mu;i++)
 
     		printf("第%d行的第一个非零元素是本矩阵第%d个元素\n",i,M.rpos[i-1]);
	for(i=1;i<=M.nu;i++)
		printf("第%d列的元素个数为%d\n",i,M.num[i-1]);
	for(i=1;i<=M.nu;i++)
		printf("第%d列的第一个元素的位置是%d\n",i,M.cpot[i-1]);	
}

/*return the matrix transpose of a given matrix*/
bool TransposeMatrix(Matrix M, Matrix *T) {
	Matrix A;
	A = M;
	T->nu = A.mu;
	T->mu = A.nu;
	T->tu = A.tu;
	for (int i = 0; i < T->tu; i++) {
		T->data[A.cpot[A.data[i].j-1]-1].i = A.data[i].j;
		T->data[A.cpot[A.data[i].j-1]-1].j = A.data[i].i;
		T->data[A.cpot[A.data[i].j-1]-1].e = A.data[i].e;
		A.cpot[A.data[i].j-1]++;	
	}
	T->num = (int*)malloc(T->nu*sizeof(int));
        T->cpot = (int*)malloc(T->nu*sizeof(int));
        memset(T->num, 0x0, T->nu*sizeof(int));
        memset(T->cpot, 0x0, T->nu*sizeof(int));
	int i = 0;
        for (i = 0; i < T->tu; i++) {
                T->num[T->data[i].j - 1]++;
        }
        T->cpot[0] = 1;
        for (i = 1; i < T->nu; i++) {
                T->cpot[i] = T->cpot[i-1] + T->num[i-1];
        }
        T->rpos[0] = 1;
        int Num[T->mu];
        memset(Num, 0x0, T->mu*sizeof(int));
        for(i = 0; i < T->tu; i++) {
                Num[T->data[i].i-1]++;
        }

}

/*take the product of the sparse matrix Q=M*N*/
bool MultiMatrix(Matrix M, Matrix N, Matrix *T) {
	if (M.nu != N.mu)
		return 0;
	T->mu = M.mu;
	T->nu = N.nu;
	T->tu = 0;
	if (M.tu*N.tu != 0)
		for (int arow = 1; arow <= M.mu; arow++) {	
			int ctemp[N.nu];
			memset(ctemp, 0x0, N.nu*sizeof(int));
			T->rpos[arow-1] = T->tu+1;
			int tp = 0;
			if(arow < M.mu)
				tp = M.rpos[arow];
			else
				tp = M.tu + 1;
			for (int p = M.rpos[arow-1]; p < tp; p++) {
				int t = M.data[p-1].j;
				int pause;
				if (t < N.mu)
					pause = N.rpos[t];
				else
					pause = N.tu + 1;
				for (int m = N.rpos[t-1]; m < pause; m++) {
					ctemp[N.data[m-1].j-1] += M.data[p-1].e*N.data[m-1].e;
				}
			}
			for (int i = 0; i < N.nu; i++) {
				if (ctemp[i] != 0) {
					T->data[T->tu].i = arow;
					T->data[T->tu].j = i + 1;
					T->data[T->tu].e = ctemp[i];
					T->tu++;
				}
			}
		}
	T->num = (int*)malloc(T->nu*sizeof(int));
        T->cpot = (int*)malloc(T->nu*sizeof(int));
        memset(T->num, 0x0, T->nu*sizeof(int));
        memset(T->cpot, 0x0, T->nu*sizeof(int));
        for (int i = 0; i < T->tu; i++) {
                T->num[T->data[i].j - 1]++;
        }
        T->cpot[0] = 1;
        for (int i = 1; i < T->nu; i++) {
                T->cpot[i] = T->cpot[i-1] + T->num[i-1];
        }

	return 1;
}

main.c

#include <stdio.h>
#include "Matrix.h"
int main () {
	Matrix M;
	Matrix N;
	Matrix A;	
	CreateMatrix(&M);
	CreateMatrix(&N);
	PrintMatrix(M);
	PrintMatrix(N);
	TransposeMatrix(M,&A);
	PrintMatrix(A);
	Matrix T;
	MultiMatrix(M,N,&T);
	PrintMatrix(T);
	DestroyMatrix(&A);
	DestroyMatrix(&T);
	DestroyMatrix(&M);
	DestroyMatrix(&N);
	return 0;
}

makefile

object = main.o Matrix.o

test : $(object)
	gcc -g -Wall -o test $(object)

main.o : Matrix.h
Matrix.o : Matrix.h

.PHONY:clean
clean:
	rm -rf *.o

运行检查:

用于测试的矩阵:

(a) M = [ 3 0 0 5 0 − 1 0 0 2 0 0 0 ] {M=} \left[ \begin{matrix} 3 &amp; 0 &amp; 0 &amp; 5\\ 0&amp;-1 &amp; 0 &amp; 0 \\ 2 &amp; 0 &amp; 0 &amp; 0 \end{matrix} \right] \tag{a} M=302010000500(a)
(b) N = [ 0 2 1 0 − 2 4 0 0 ] {N=} \left[ \begin{matrix} 0 &amp; 2 \\ 1 &amp; 0 \\ -2 &amp; 4 \\ 0 &amp; 0 \end{matrix} \right] \tag{b} N=01202040(b)

M.data
ije
113
145
22-1
312
N.data
ije
122
211
31-2
324
M*N结果:
ije
126
21-1
324
输入文件input.txt
3 4 4
1 1 3
1 4 5
2 2 -1
3 1 2
4 2 4
1 2 2
2 1 1
3 1 -2
3 2 4
输出文件test.txt
3行4列4个非零元素。
行  列  元素值
 1   1       3
 1   4       5
 2   2      -1
 3   1       2
第1行的第一个非零元素是本矩阵第1个元素
第2行的第一个非零元素是本矩阵第3个元素
第3行的第一个非零元素是本矩阵第4个元素
第1列的元素个数为2
第2列的元素个数为1
第3列的元素个数为0
第4列的元素个数为1
第1列的第一个元素的位置是1
第2列的第一个元素的位置是3
第3列的第一个元素的位置是4
第4列的第一个元素的位置是4
4行2列4个非零元素。
行  列  元素值
 1   2       2
 2   1       1
 3   1      -2
 3   2       4
第1行的第一个非零元素是本矩阵第1个元素
第2行的第一个非零元素是本矩阵第2个元素
第3行的第一个非零元素是本矩阵第3个元素
第4行的第一个非零元素是本矩阵第5个元素
第1列的元素个数为2
第2列的元素个数为2
第1列的第一个元素的位置是1
第2列的第一个元素的位置是3
4行3列4个非零元素。
行  列  元素值
 1   1       3
 1   3       2
 2   2      -1
 4   1       5
第1行的第一个非零元素是本矩阵第1个元素
第2行的第一个非零元素是本矩阵第0个元素
第3行的第一个非零元素是本矩阵第0个元素
第4行的第一个非零元素是本矩阵第0个元素
第1列的元素个数为2
第2列的元素个数为1
第3列的元素个数为1
第1列的第一个元素的位置是1
第2列的第一个元素的位置是3
第3列的第一个元素的位置是4
3行2列3个非零元素。
行  列  元素值
 1   2       6
 2   1      -1
 3   2       4
第1行的第一个非零元素是本矩阵第1个元素
第2行的第一个非零元素是本矩阵第2个元素
第3行的第一个非零元素是本矩阵第3个元素
第1列的元素个数为1
第2列的元素个数为2
第1列的第一个元素的位置是1
第2列的第一个元素的位置是2
linux运行程序确实舒服,直接命令行就可以读取文本
make
#运行makefile
./test < input.txt > test.txt
#运行生成的可执行文件test
make clean
#清理.o文件
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值