稀疏矩阵(三元组顺序表实现)

 定义了一个稀疏矩阵类,有转置和相乘,相加三个功能,主要是熟悉稀疏矩阵的三元组顺序表存储的一些操作,和一般的矩阵不同的地方,两个转置的算法,第一个是较容易想到的,书上管它叫“按需点菜”法,就是按一开始列的顺序,一个个转为新矩阵中行的顺序。第二个叫作“按位就坐”法,就是条件两个辅助数组,确定每一列中第一个非零元在稀疏矩阵中存储的位置,从而可以在操作时,更为容易地实现矩阵转置后可以按行递增的顺序排列整齐。

稀疏矩阵的乘法,我自己觉得确实有难度,研究了一天才研究清楚这个东西,如果按和一般矩阵那样去做的话,虽然会浪费多一点时间,但是代码量和思考量就相对少得多,但是这也是算法的特别之处吧。 下面是代码,有较为清楚的解释

文件"dingyi.h"

#define maxtemr 100
class SparseMatrix; //向前声明

class MatrixTerm//矩阵元素类
{
public:
	int row;//行
	int col;//列
	int value;//值
	friend SparseMatrix;
};

class SparseMatrix
{
private:
	int Rows;//行数
	int Cols;//列数
	int Terms;//非零项个数
	MatrixTerm smArray[maxtemr];//maxterm是常数,maxterm<<Rows*Cols
	int cpot[20];
public:
	void InitMatrix();
	SparseMatrix Transpose1(); //矩阵转置算法1
	SparseMatrix Transpose2();//矩阵转置算法2
	bool Multiply(SparseMatrix b,SparseMatrix &q);//矩阵相乘
	bool Add(SparseMatrix b,SparseMatrix &c);//矩阵相加
	void print();
};


文件"shixian.cpp"

#include"dingyi.h"
#include<iostream>
using namespace std;

void SparseMatrix::InitMatrix()
{
	Terms=0;
	int r,c,s=0,val;
	cout<<"输入要创建的矩阵的行数和列数:";
	cin>>r>>c;
	Rows=r;
	Cols=c;
	
	cout<<"请输入矩阵中各元素的值,请输入"<<r*c<<"个整数"<<endl;
	for(int i=0;i<r;i++)
	{
		for(int j=0;j<c;j++)
		{
			cin>>val;
			if(val!=0)
			{
				smArray[s].row=i;
				smArray[s].col=j;
				smArray[s].value=val;
				s++;
			}
		}
	}
	Terms=s;
	int *num=new int[r];

	for(int m=0;m<Rows;m++)
		num[m]=0;

	for(m=0;m<Terms;m++)
		++num[smArray[m].row];
	
	cpot[0]=0;

	for(m=1;m<Rows;m++)
		cpot[m]=cpot[m-1]+num[m-1];
}

SparseMatrix SparseMatrix::Transpose1()
{
	SparseMatrix b;
	b.Rows=Cols;
	b.Cols=Rows;
	b.Terms=Terms;
	if(b.Terms)
	{
		int currentB=0;
		for(int c=0;c<Cols;c++)
			for(int i=0;i<Terms;i++)
				if(smArray[i].col==c)//找到c列中的元素
				{
					b.smArray[currentB].row=c;
					b.smArray[currentB].col=smArray[i].row;
					b.smArray[currentB].value=smArray[i].value;
					currentB++;
				}
	}
	return b;
}

SparseMatrix SparseMatrix::Transpose2()
{
	SparseMatrix b;
	b.Rows=Cols;
	b.Cols=Rows;
	b.Terms=Terms;
	
	int *num;
	int *cpot;
	num=new int[Cols];
	cpot=new int[Cols];

	if(b.Terms)
	{
		for(int c=0;c<Cols;c++)
			num[c]=0;
	
		for(c=0;c<b.Terms;c++)
			++num[smArray[c].col];
		cpot[0]=0;
		
		for(c=1;c<Cols;c++)
			cpot[c]=cpot[c-1]+num[c-1];
		
		for(int p=0;p<b.Terms;p++)
		{
			int j=smArray[p].col;
			int q=cpot[j];
			b.smArray[q].row=smArray[p].col;
			b.smArray[q].col=smArray[p].row;
			b.smArray[q].value=smArray[p].value;
			++cpot[j];
		}
	}
	return b;
}


bool SparseMatrix::Multiply(SparseMatrix b,SparseMatrix &q)
{
	/*
	返回两个矩阵的乘积,用C来装
	采用与第二种转置的算法一样的做法,给每个矩阵增加一个数组,用来记录每一行第一个非零值在
	在矩阵smArray[]中的位置,这个数组就是cpot[],有这样结构的稀疏矩阵叫做行逻辑连接顺序表
	计算过程如下:  
	1.    由于矩阵a和Q的行数相等并且C语言以行为主序进行存储,所以以a进行逐行的扫描。  
	2.    使Q的此行逻辑表的序号等于其非零元个数Q.terms+1,以表示其行的首个元素的序号。  
	3.    从行中找到a的非零元,并以它的列值为b的行号,对b进行行的扫描,若存在,
		  则依次计算它们,并把其值累加到一个以b中这个对应非零元的列值为序号的临时数组q_sum[q_col]中。  
	4.    在a的当前行完成扫描后,将q_sum[q_col]不为0的值,压入到Q矩阵的三元组,累加Q.Terms
	*/
	
	int t1,t2,q_col;
	int *q_sum;//用于存放结果的临时数组
	
	if(this->Cols!=b.Rows)
		return false;
	
	q.Rows=this->Rows;
	q.Cols=b.Cols;
	q.Terms=0;
	q_sum=new int[b.Cols];
	if(this->Terms*b.Terms!=0)
	{
		for(int a_row=0;a_row<this->Rows;a_row++)//以a的每一行为标准,进行运算
		{
			for(int i=0;i<b.Cols;i++)
				q_sum[i]=0;
			
			q.cpot[a_row]=q.Terms;
			
			if(a_row<this->Rows-1)
				t1=this->cpot[a_row+1];
			else
				t1=this->Terms;
			
			for(int p=this->cpot[a_row];p<t1;p++)
			{
				int b_row=this->smArray[p].col;
				
				if(b_row<b.Rows-1)
					t2=b.cpot[b_row+1];
				else
					t2=b.Terms;
				
				for(int q=b.cpot[b_row];q<t2;q++)
				{
					q_col=b.smArray[q].col;
					q_sum[q_col]+=this->smArray[p].value*b.smArray[q].value;
				}
			}
			
			for(q_col=0;q_col<q.Cols;q_col++)
				if(q_sum[q_col])
				{
					q.smArray[q.Terms].row=a_row;
					q.smArray[q.Terms].col=q_col;
					q.smArray[q.Terms].value=q_sum[q_col];
					++q.Terms;
				}
		}
	}

	return true;
}

bool SparseMatrix::Add(SparseMatrix b,SparseMatrix &c)
{
	/*
	计算过程是这样的,一次扫描两个矩阵a,b的smArray[]中的每个数据,
	比较两个数据,如果行号相同,则比较列号,若列号不想等则将列号小的存入矩阵c
	的smArray[]中,若列号相等,则计算,计算完非零,再存入c中;
	如果a的当前项行号小于b的当前项行号,那么就将a的项存入c,反之,存b
	*/
	if(this->Rows!=b.Rows||this->Cols!=b.Cols)
		return false;
	int sum=0;
	int p=0;//指向a的当前项
	int t=0;//指向b的当前项
	int k=0;//指向c的当前项
	while( p<this->Terms && t<b.Terms)
	{
		if(this->smArray[p].row==b.smArray[t].row)
		{
			if(this->smArray[p].col==b.smArray[t].col)
			{
				sum=this->smArray[p].value+b.smArray[t].value;
				if(sum)
				{
					c.smArray[k].row=b.smArray[t].row;
					c.smArray[k].col=b.smArray[t].col;
					c.smArray[k].value=sum;
					k++;p++;t++;
				}
			}
			else if(this->smArray[p].col<b.smArray[t].col)
			{
				c.smArray[k].row=this->smArray[p].row;
				c.smArray[k].col=this->smArray[p].col;
				c.smArray[k].value=this->smArray[p].value;
				k++;p++;
			}
			else
			{
				c.smArray[k].row=b.smArray[t].row;
				c.smArray[k].col=b.smArray[t].col;
				c.smArray[k].value=b.smArray[t].value;
				k++;t++;
			}
		}
		else if(this->smArray[p].row<b.smArray[t].row)
		{
			c.smArray[k].row=this->smArray[p].row;
			c.smArray[k].col=this->smArray[p].col;
			c.smArray[k].value=this->smArray[p].value;
			k++;p++;
		}
		else
		{
			c.smArray[k].row=b.smArray[t].row;
			c.smArray[k].col=b.smArray[t].col;
			c.smArray[k].value=b.smArray[t].value;
			k++;t++;
		}
	}
	while(p<this->Terms)
	{
		c.smArray[k].row=this->smArray[p].row;
		c.smArray[k].col=this->smArray[p].col;
		c.smArray[k].value=this->smArray[p].value;
		k++;p++;
	}
	while(t<b.Terms)
	{
		c.smArray[k].row=b.smArray[t].row;
		c.smArray[k].col=b.smArray[t].col;
		c.smArray[k].value=b.smArray[t].value;
		k++;t++;
	}
	c.Rows=b.Rows;
	c.Cols=b.Cols;
	c.Terms=k;
	return true;
}

void SparseMatrix::print()
{
	int p=Terms;
	for(int i=0;i<p;i++)
		cout<<"smArray["<<smArray[i].row<<"]["<<smArray[i].col<<"]= "<<smArray[i].value<<endl;
	cout<<endl;
}


测试函数"main.cpp"

#include"dingyi.h"

#include<iostream.h>

int main()
{
	SparseMatrix sm,T,F;
	sm.InitMatrix();
	cout<<"矩阵sm 为:"<<endl;
	sm.print();
	T=sm.Transpose2();
	//T=sm.Transpose1();
	cout<<"矩阵sm的转置为: "<<endl;
	T.print();

	SparseMatrix M;
	M.InitMatrix();
	cout<<"矩阵M为:"<<endl;
	M.print();

	if(sm.Multiply(M,F))
	{
		cout<<"矩阵M与矩阵sm 相乘为:"<<endl;
		F.print();
	}
	
	SparseMatrix N,P;
	N.InitMatrix();
	if(sm.Add(N,P))
	{
		cout<<"矩阵sm和N相加的矩阵为:"<<endl;
		P.print();
	}
	return 0;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值