头文件:
#ifndef ADT_TSMatrix_H #define ADT_TSMatrix_H #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define MYOVERFLOW -2 #define MAXSIZE 12500 //假设非零元素个数的最大值为12500 typedef int Status; typedef int Elemtype;//用指定标识符Elemtype代表int类型,顾名思义表示元素类型为int型 typedef struct{ int i, j; //该非零元素的行下标和列下标 Elemtype e; }Triple; typedef struct{ Triple data[MAXSIZE + 1];//非零元三元组表,data[0]未用 int mu, nu, tu; //矩阵的行数,列数和非零元个数 }TSMatrix; //-------------稀疏矩阵的基本操作------------ Status CreateSMatrix(TSMatrix &M);//操作结果:创建稀疏矩阵M。 Status DestroySMatrix(TSMatrix &M);//在稀疏矩阵存在的情况下,销毁稀疏矩阵M Status PrintSMatrix(TSMatrix M);//稀疏矩阵存在的情况下,输出稀疏矩阵M Status CopySMatrix(TSMatrix M, TSMatrix &T);//稀疏矩阵M存在,由稀疏矩阵M复制得到T Status AddSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q); //稀疏矩阵M与N的行数和列数对应相等,求得稀疏矩阵Q=M+N。 Status SubtMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q); //稀疏矩阵M与N的行数和列数对应相等,求得稀疏矩阵Q=M-N。 Status MultSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q); //稀疏矩阵M的列数等于N的行数,求得稀疏矩阵Q=M*N Status TransposeSMatrix(TSMatrix M, TSMatrix &T); //稀疏矩阵M存在,求得稀疏矩阵M的转置矩阵T Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T); //稀疏矩阵M存在,求得稀疏矩阵M的装置矩阵T,但这是一种效率更高的转置算法 #endif
上述操作的实现:
#include"stdafx.h" //-------------稀疏矩阵的基本操作------------ Status CreateSMatrix(TSMatrix &M)//操作结果:创建稀疏矩阵M。 { cout << "please input the number of the row:"; cin >> M.mu; cout << "please input the number of the column:"; cin >> M.nu; cout << "please input the number of the elem which is not equal to zero:"; cin >> M.tu; //输入稀疏矩阵的行数、列数、非零元素数 cout << "please input the data :" << endl;//输入矩阵的元素,一次输入行的位置,列的位置和元素的值 for (int i1 = 1; i1 <= M.tu; ++i1){ cin >> M.data[i1].i >> M.data[i1].j >> M.data[i1].e; } return OK; } Status DestroySMatrix(TSMatrix &M)//在稀疏矩阵存在的情况下,销毁稀疏矩阵M { if (M.tu != 0){ for (int ii = 1; ii <= M.tu; ++ii){ M.data[ii].i = 0; M.data[ii].j = 0; M.data[ii].e = 0; } M.mu = 0; M.tu = 0; M.nu = 0; return OK; } else return ERROR; } Status PrintSMatrix(TSMatrix M)//稀疏矩阵存在的情况下,输出稀疏矩阵M { if (M.tu == 0)return ERROR; else { cout << 'i' << " " << "j" << " " << "e" << endl; for (int ii = 1; ii <= M.tu; ++ii){ cout << M.data[ii].i << " " << M.data[ii].j << " " << M.data[ii].e << endl; } cout << endl; } return OK; } Status CopySMatrix(TSMatrix M, TSMatrix &T)//稀疏矩阵M存在,由稀疏矩阵M复制得到T { T.mu = M.mu; T.nu = M.nu; T.tu = M.tu; for (int ii = 1; ii <= M.tu; ++ii){ T.data[ii].i = M.data[ii].i; T.data[ii].j = M.data[ii].j; T.data[ii].e = M.data[ii].e; } return OK; } Status AddSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q) //稀疏矩阵M与N的行数和列数对应相等,求得稀疏矩阵Q=M+N。 { if (M.mu == N.mu&&M.nu == N.nu){//稀疏矩阵M和N的行数列数相等,才进行运算 Q.mu = M.mu; //为Q的行和列赋值 Q.nu = M.nu; int M_temp = 1, N_temp = 1; //这是M和N当前的位置都为1 int len = 1; //这是Q的当前非零元个数 for (; M_temp<=M.tu&&N_temp<=N.tu; ++len){ if (M.data[M_temp].i < N.data[N_temp].i){//如果M的当前非零元素的行值小于N的,则直接把M的这个元素拷贝给Q Q.data[len].i = M.data[M_temp].i; Q.data[len].j = M.data[M_temp].j; Q.data[len].e = M.data[M_temp].e; //M的当前位置向前走一步 ++M_temp; } else if (M.data[M_temp].i == N.data[N_temp].i){//如果M的当前非零元素的行值等于N的,则还需比较列值 if (M.data[M_temp].j < N.data[N_temp].j){ //如果M的列值<N的列值,这把M的这个元素拷贝给Q Q.data[len].i = M.data[M_temp].i; Q.data[len].j = M.data[M_temp].j; Q.data[len].e = M.data[M_temp].e; ++M_temp; //M的当前位置向前走一步 } else if (M.data[M_temp].j == N.data[N_temp].j){//如果M的列值=N的列值 if (M.data[M_temp].e != -N.data[N_temp].e){//如果这个位置相同的两个元素之和不为零,则将相应的e值拷贝给Q Q.data[len].i = M.data[M_temp].i; Q.data[len].j = M.data[M_temp].j; Q.data[len].e = M.data[M_temp].e + N.data[N_temp].e; } else --len; //如果和=0,则在这个循环中,Q的长度并未增加,将len减去1 ++N_temp; //N的当前位置向前走一步 ++M_temp; //M的当前位置向前走一步 } else{ //如果M的列值>N的列值,把N的这个元素拷贝给Q Q.data[len].i = N.data[N_temp].i; Q.data[len].j = N.data[N_temp].j; Q.data[len].e = N.data[N_temp].e; ++N_temp; //N的当前位置向前走一步 } } else{ //如果M的行值>N的行值,把N的这个元素拷贝给Q Q.data[len].i = N.data[N_temp].i; Q.data[len].j = N.data[N_temp].j; Q.data[len].e = N.data[N_temp].e; ++N_temp; //N的当前位置向前走一步 } } if (M_temp > M.tu){ //如果是M的元素先检查完,则把N的剩下的元素拷贝给Q for (; N_temp <= N.tu; ++N_temp, ++len){ Q.data[len].i = N.data[M_temp].i; Q.data[len].j = N.data[M_temp].j; Q.data[len].e = N.data[M_temp].e; } } else{ for (; M_temp <= M.tu; ++M_temp,++len){ //如果是N的元素先检查完,则把M的剩下的元素拷贝给Q Q.data[len].i = M.data[M_temp].i; Q.data[len].j = M.data[M_temp].j; Q.data[len].e = M.data[M_temp].e; } } //同时检查完,则不需要其他操作 Q.tu = --len; return OK; } return ERROR; } Status SubtMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q) //稀疏矩阵M与N的行数和列数对应相等,求得稀疏矩阵Q=M-N。 { for (int i = 1; i <= N.tu; ++i) //减法只是加法的另一种形式而已,将矩阵N的全部数据元素取反, N.data[i].e = -N.data[i].e; //然后按照加法的规则,进行运算 if(AddSMatrix(M, N, Q))return OK; else return ERROR; } Status MultSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q) //稀疏矩阵M的列数等于N的行数,求得稀疏矩阵Q=M*N { if (M.nu != N.mu)return ERROR; //如果M的列数和N的行数不相等,则矩阵无法相乘 Q.mu = M.mu; Q.nu = N.nu; Q.tu = 0; int M_rpos[50] = { 0 }, N_rpos[50] = { 0 }, M_num[50] = { 0 }, N_num[50] = { 0 }, ctemp[50]; M_rpos[1] = 1; N_rpos[1] = 1; //M和N的第一行的第一个非零元素的位置一定是1 for (int i = 1; i <= M.tu; ++i) //求得M中每一行元素的个数 ++M_num[M.data[i].i]; for (int i = 1; i <= N.tu; ++i) //求得N中每一行元素的个数 ++N_num[N.data[i].i]; for (int i = 2; i <= M.mu; ++i) //求得M中每一行第一个非零元素的位置 M_rpos[i] = M_rpos[i - 1] + M_num[i-1]; for (int i = 2; i <= N.mu; ++i) //求得N中每一行第一个非零元素的位置 N_rpos[i] = N_rpos[i - 1] + N_num[i - 1]; if (M.tu*N.tu != 0){ //如果M和N中都有非零元素才进行下面的步骤 for (int row = 1; row <= M.mu; ++row){//按照M中的行序对Q的结果进行求值 for (int i = 1; i < 50; ++i) //每次循环都要将这个临时累加器清零 ctemp[i] = 0; int tp = 0, t = 0, ccol = 0, brow = 0; if (row < M.mu)tp = M_rpos[row + 1];//如果行数<M的最大行数,则每行的下一行第一个非零元素的位置为M_rpos[row+1] else tp = M.tu + 1; //最后一行的为M.tu+1 for (int p = M_rpos[row]; p < tp; ++p){//当前行的第一个元素的位置赋予P brow = M.data[p].j; //得到该元素的列数,从而对N相等的行进行运算 if (brow < N.mu)t = N_rpos[brow + 1];//如果行数<N的最大行数,则每行的下一行第一个非零元素的位置为N_rpos[row+1] else t = N.tu + 1; //最后一行的为N.tu+1 for (int q = N_rpos[brow]; q < t; ++q){ ccol = N.data[q].j; //将该列的结果暂时保存在ctemp[ccol]中,因为 ctemp[ccol] += M.data[p].e*N.data[q].e; // 只有当该行全部运算完,才知道Q的该行的第ccol列确切的值 } } for (ccol = 1; ccol <= Q.nu;++ccol)//将结果赋予Q if (ctemp[ccol]){ Q.data[++Q.tu].i = row; Q.data[Q.tu].j = ccol; Q.data[Q.tu].e = ctemp[ccol]; } } } return OK; } Status TransposeSMatrix(TSMatrix M, TSMatrix &T) //稀疏矩阵M存在,求得稀疏矩阵M的转置矩阵T { if (M.tu > 0){ T.mu = M.nu; T.nu = M.mu; T.tu = 1; for (int i = 1; i <= M.nu; ++i){ for (int j = 1; j <= M.tu; ++j){ if (M.data[j].j == i){ T.data[T.tu].i = M.data[j].j; T.data[T.tu].j = M.data[j].i; T.data[T.tu].e = M.data[j].e; ++T.tu; } } } --T.tu; return OK; } return ERROR; } Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T) //稀疏矩阵M存在,求得稀疏矩阵M的装置矩阵T,但这是一种效率更高的转置算法 { T.mu = M.nu; T.nu = M.mu; T.tu = M.tu; if (M.tu){ int num[50] = { 0 }; int cpot[50] = { 0 }; cpot[1] = 1; for (int i = 1; i <= M.tu; ++i) ++num[M.data[i].j]; for (int i = 2; i <= M.nu; ++i) cpot[i] = cpot[i - 1] + num[i - 1]; for (int i = 1; i <= M.tu; ++i){ int column = M.data[i].j; int pos = cpot[column]; T.data[pos].i = M.data[i].j; T.data[pos].j = M.data[i].i; T.data[pos].e = M.data[i].e; ++cpot[column]; } } return OK; }
对于两种转置算法和矩阵加法的验证,主函数:
// TSMatrix.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { TSMatrix M, T,Q,t; CreateSMatrix(M); TransposeSMatrix(M, T); FastTransposeSMatrix(M, t); PrintSMatrix(T); PrintSMatrix(t); AddSMatrix(M, T, Q); PrintSMatrix(Q); return 0; }
结果:
对于稀疏矩阵乘法的验证,主函数:
// TSMatrix.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { TSMatrix M, T, Q; CreateSMatrix(M); CreateSMatrix(T); MultSMatrix(M, T, Q); PrintSMatrix(Q); return 0; }
结果: