#include "SparseMatrix.h"
#include "SparseMatrix.cpp"
#include <iostream>//C++里库文件不要加.h后缀,此处<iostream.h>不被识别
using namespace std;
int main()
{
SparseMatrix<int> a,b;
a.ShowPrivates();
cout<<endl;
a.Input();
b.Input();
a.Transpose();
a.Multiply(b);
return 0;
}
#ifndef SPARSEMATRIX_CPP
#define SPARSEMATRIX_CPP
#include <iostream>
#define MaxTerms 50
static exnum1,exnum2;//用来纪录下一次录入的非零元素是否与它前一个元素相同。
template<class type> class SparseMatrix;//前向引用声明,类名后面不用加<Type>.
//总结:需要加<Type>的情况1,实现模板类的成员函数时候template<class Type> 返回值类型(返回这个魔板类类型也要加<Type>) 类名<Type>::函数名
// 2,type没有实例化的时候定义对象,要加<Type>
template<class Type> class Trituple
{
friend class SparseMatrix < Type > ;//声明SparseMatrix是其友元类,
//两个类协同完成矩阵构造。
private:
int row, col; //非零元素的行号、列号
Type value; //非零元素的值,type一般就是int float double之间选择
};
//养成好习惯,相对独立两个代码段间空行隔开
template<class Type> class SparseMatrix
{
//对象:是一个三元组< row, column, value >的集合,其中,row和column是整数,记忆矩阵
//元素所在的行号和列号,而value是矩阵元素的值。
public:
SparseMatrix(int MaxRow=2, int Matrix=2,int Maxterms=2)
{
Rows=MaxRow;
Cols=Matrix;
if(Maxterms<MaxRow*Matrix)
Terms=Maxterms;
else
{
cerr<<"Terms is out of range,it should be picked from 0 to"<<MaxRow*Matrix<<endl;
exit(1);
}
std::cout<<"Sparse Constructor Called"<<endl;//因为这个.h没有声明命名空间using namespace std;,所以要用std::
}//构造函数
//建立一个MaxRow行,Maxcol列的稀疏矩阵.
void ShowPrivates( );
void Transpose( );
//对矩阵this指示得三元组中各个三元组交换行列值,得到转置矩阵,
//并返回SparseMatrix<Type>类型的一个矩阵
void Input( );
void Output( );
void Add(SparseMatrix < Type > b);
//当矩阵a(*this指针)b的行、列相同时,将这两个矩阵的对应项相加。
void Multiply(SparseMatrix < Type > b);
//按公式c[ii][j]=∑(a[i][k]*b[k][j])实现矩阵a和b相乘。k=0,1,2...,a的列数为-1。
private:
int Rows, Cols, Terms ;
//行数,列数,某对象非零元素个数
Trituple<Type> smArray[MaxTerms];//每个SpareMatrix对象可含有的非零元素上限
Type* p;//用来输出输入矩阵用
};
#include "SparseMatrix.cpp"
#endif
#ifndef Sparse_CPP
#define Sparse_CPP
#include<iostream>
#include"SparseMatrix.h"
template<class Type> void SparseMatrix<Type>::ShowPrivates( ) //输出 私有成员值
{
cout<<"行数: "<<Rows<<endl;
cout<<"列数: "<<Cols<<endl;
}
template<class Type> void SparseMatrix<Type>::Transpose(){
//将稀疏矩阵a(*this指针)转置,结果在稀疏矩阵b中。
SparseMatrix<Type> b(Cols, Rows); //创建一个稀疏矩阵类的对象b
b.Rows = Cols; //矩阵b的行数 = 矩阵a的列数
b.Cols = Rows; //矩阵b的列数 = 矩阵a的行数
b.Terms = Terms; //矩阵b的非零元素 = 矩阵a的非零元数
if( Terms > 0){ //非零元素个数不为零
int CurrentB =0; //存放位置指针
for(int k=0; k<Cols; k++ ) //按列号做扫描,做Cols趟
for(int i=0; i< Terms; i++) //在数组中找列号位k的三元组
if(smArray[i].col==k){ //第i个三元组中元素的列号为k
b.smArray[CurrentB].row = k; //新三元组的行号
b.smArray[CurrentB].col = smArray[i].row; //新三元组的列号
b.smArray[CurrentB].value = smArray[i].value; //新三元组的值
CurrentB ++; //存放指针进1
}
}
p=new Type[Rows*Cols];//建立动态数组,全部清零,并为记录非零元素做准备
for(int j=0;j<Rows*Cols;j++)
p[j]=Type(0);
for(int i=0;i<Terms;i++)
p[(b.smArray[i].row-1)*Cols+b.smArray[i].col-1]=b.smArray[i].value;
for(j=0;j<Rows*Cols;j++)
{
cout<<p[j]<<" ";
if((j+1)%Cols==0)
cout<<endl;
}
}
template<class T> void SparseMatrix<T> :: Multiply(SparseMatrix<T> b)
//两个稀疏矩阵A(*this指示)与B(参数表中的b)相乘,结果在Result中。
{
if (Cols!=b.Rows){
cout<<"Incompatible matrices"<<endl;
cerr<<"the rows and the cols are not equal"<<endl;
}
if (Terms==MaxTerms || b.Terms==MaxTerms){
cout<<"one additional space in a or b needed"<<endl;
cerr<<"the rows and the cols are not equal"<<endl;
}
int *rowSize = new int[b.Rows];
int *rowStart = new int[b.Rows+1];
T *temp = new T[b.Cols];
SparseMatrix<T> result(Rows, Cols);
for (int i=0; i<b.Rows; i++) rowSize[i] = 0;
for (i=0; i<=b.Terms; i++) rowSize[smArray[i].row]++;
rowStart[0] = 0;
for(i=1; i<=b.Rows; i++) rowStart[i] = rowStart[i-1] + rowSize[i-1];
int Current = 0, lastInResult = -1;
while (Current < Terms){
int RowA = smArray[Current].row;
for (i=0; i<b.Cols; i++) temp[i] = 0;
while (Current<Terms && smArray[Current].row==RowA){
int ColA = smArray[Current].col;
for (i=rowStart[ColA]; i<rowStart[ColA+1]; i++){
int ColB = b.smArray[i].col;
temp[ColB] = temp[ColB] + smArray[Current].value * b.smArray[i].value;
}
Current++;
}
for (i=0; i<b.Cols; i++)
if (temp[i]!=0){
lastInResult++;
result.smArray[lastInResult].row = RowA;
result.smArray[lastInResult].col = i;
result.smArray[lastInResult].value = temp[i];
}
}
result.Rows = Rows; result.Cols = b.Cols; result.Terms = lastInResult+1;
delete[ ]rowSize; delete[ ]rowStart; delete[ ]temp;
result.p=new Type[Rows*Cols];//建立动态数组,全部清零,并为记录非零元素做准备
for(int j=0;j<Rows*Cols;j++)
result.p[j]=Type(0);
for( i=0;i<Terms;i++)
result.p[(result.smArray[i].row-1)*Cols+result.smArray[i].col-1]=result.smArray[i].value;
for(j=0;j<Rows*Cols;j++)
{
cout<<result.p[j]<<" ";
if((j+1)%Cols==0)
cout<<endl;
}
}
template<class Type> void SparseMatrix<Type>::Add(SparseMatrix<Type> c)
{
if(c.Rows==Rows&&c.Cols==Cols)
{
p=new Type [Rows*Cols];
for(int j=0;j<Rows*Cols;j++)
p[j]=Type(0);//因为可以做加法,创建一个a[Rows][Cols]的动态数组来存放值,初始时候清零
for(int k=0;k<Terms;k++)
{
p[(smArray[k].row-1)*Cols+smArray[k].col-1]+=smArray[k].value;//把每个a[smArray[i].row][smArray[i].col]的位置加上smArray[i].value的值
p[((c.smArray[k]).row-1)*Cols+(c.smArray[k]).col-1]+=(c.smArray[k]).value;//把每个a[(c.smArray[i]).row][(c.smArray[i]).col]的位置加上(c.smArray[i]).value的值
}
cout<<"the result is: "<<endl;
for(j=0;j<Rows*Cols;j++)//输出这个矩阵
{
cout<<p[j]<<" ";
if((j+1)%Cols==0)
cout<<endl;
}//以上得到那个结果矩阵。
//注意到这个结果矩阵的Rows Cols跟调用它的对象一样。但是Terms不一定一样,所以在返回对象事后注意返回对象的Terms是多少。
//以下得到terms与那个对象。注意:如果这个函数返回值为void,以下部分至return b可以删去。
}
/*int test=Row2/2;+1//防止Rows=1的情况发生,那时test=0,没有课匹配的行数。
for(j=0;j<Cols;j++)
{
for(int l=0;l<Rows;l++)
cout<<
/*输出这个算式如:A+B=C;注意到计算机是逐行扫描的,所以要这样做:第一步:输出this的第一行,并打出3各空格,并且接着输出c对象的那个数组
第二步:计算出Rows/2的值,这行不仅用来输出数字,而且在输出完第一个数组的那行后,输出一个空格,然后一个+号,然后又一个空格。之后输出c这行的数字
第三步:仿照第一步来做。所以每行的操作依次为,输出数组某行,接着判断是否输出+,接着继续输出c的数组那一行
以后补充这里如果逐行输入
*/
else
cerr<<"Cols and Rows are not equal,so the operation stops"<<endl;
}
template<class Type> void SparseMatrix<Type>::Output( ) //输出 Trituple数组
{
if(p==0)
{
cerr<<"Please input the array first!"<<endl;
exit(1);
}//这个机制用来防止未赋值就输出。
cout<<"矩阵为"<<Rows<<"*"<<Cols<<"的矩阵"<<endl;
for(int j=0;j<Rows*Cols;j++)//输出这个矩阵
{
cout<<p[j]<<" ";
if((j+1)%Cols==0)
cout<<endl;
}
}
template<class Type> void SparseMatrix<Type>::Input( )
{
//输入对象为Maxtr,输入流对象为InStream
cout << "您已经建立了一个SparseMatrix对象: "<<Rows<<"*"<<Cols<<"的矩阵"<<endl;
cout << "包含最多"<<MaxTerms<<"个非零元素"<<"现在请输入矩阵内容: "<<endl;
p=new Type[Rows*Cols];//建立动态数组,全部清零,并为记录非零元素做准备
for(int j=0;j<Rows*Cols;j++)
p[j]=Type(0);
for(int i=0;i<Terms;i++)//输入那些三元组
{
do{
cout<<"第"<<i<<"个非零元素的行:范围0~"<<Rows<<":"<<endl;
cin>>smArray[i].row;
}
while(smArray[i].row>Rows);
do
{
cout<<"第"<<i<<"个非零元素的列:范围0~"<<Cols<<":"<<endl;
cin>>smArray[i].col;//刚才这里有个错误,多写了个左括号。 "the left parenthesis "("found in ......is not matched correctly,但是错误指针指向的是这个
//函数末尾,所以以后看错误行要看行数,不一定看那个指针。
}
while(smArray[i].col>Cols);
if(exnum1!=smArray[i].row||exnum2!=smArray[i].col)
{
cout<<"第"<<i<<"个非零元素的值:"<<endl;
cin>>smArray[i].value;
cout<<endl;
exnum1=smArray[i].row;
exnum2=smArray[i].col;
}
else i--;//即回到上一次输入的地方了。这个机制防止两次输入的元素是同一个元素。
p[(smArray[i].row-1)*Cols+smArray[i].col-1]=smArray[i].value;//此处需要用新方法,
//防止多次访问Maxtr变量
}
for(j=0;j<Rows*Cols;j++)//输出这个矩阵,这里迭代变量j就是上面那个j,不能重复定义。j有块作用域,作用于整个Input函数的大括号之间,不是语句括号之间
{
cout<<p[j]<<" ";
if((j+1)%Cols==0)
cout<<endl;
}
cout<<endl<<endl<<endl;
}
#endif
请教大家其中Multiply 函数,和那个Transpose()函数的代码有些什么问题。还有如果这些函数希望返回一个对象,那么代码如何更改。
这个代码比较长。大家有耐心挑战的话,希望帮助~〉谢谢了哦