用三列二维数组表示的稀疏矩阵类

1.稀疏矩阵:矩阵中绝大多数的元素值为零,只有少数的非零元素值;

2.对稀疏矩阵采用压缩存储的目的是为了节省存储空间,并且,稀疏矩阵压缩存储后,还要能够比较方便地访问其中的没个元素(包括零元素和非零元素);

3.对稀疏矩阵进行压缩存储有两种方法:稀疏矩阵的三列二维数组表示和十字链表方法。

稀疏矩阵的三列二维数组表示:

    (1)每个非零元素用三元组表示:(i,j,v)分别对应(行,列,非零元素);

    (2) 为了表示唯一性,除了每个非零元素用一个三元组表示外,在所有的非零元素三元组之前添加一组信息(I,J,V)对应(总行数,总列数,非零元素个数),也就是说,我们要确定确切的稀疏矩阵,必须先知道该稀疏矩阵的总行数,总列数,非零个数;

    (3)为了便于在三列二维数组B中访问稀疏矩阵A中的各元素,通常还附设两个长度与稀疏矩阵A的行数相同的向量POS与NUM。其中POS[K]表示稀疏矩阵A中的第k行的第一个非零元素(如果有的话)在三列二维组B中的行号;NUM[k]表示稀疏矩阵A中第k行中非零元素的个数;

pos[0]=0; pos[k]=pos[k-1]+num[k-1]

4.三列二维数组表示的稀疏矩阵类如下:

文件名:X_Array.h

#include <iostream>
#include <iomanip>
using namespace std;
template <class T>
struct B
{
	int i;   //非零元素所在行号
	int j;   //非零元素所在列号
	T v;     //非零元素值
};
//三列二维数组表示的稀疏矩阵类
template <class T>
class X_Array
{
private:
	int mm;      //稀疏矩阵行数
	int nn;      //稀疏矩阵列数
	int tt;      //非零个数
	B<T> *bb;    //三列二维数组空间
	int *pos;    //某行第一个非零元素在b中的下标
	int *num;    //某行非零元素的个数
public:
	void in_X_Array();                    // 以三元组形式键盘输入稀

	
	void cp_X_Array(int,int,int,B<T>[]);  // 复制三元数组
	void th_X_Array(int,int,T[]);         // 由一般稀疏矩阵转换
	void prt_X_Array();                   // 按行输出稀疏矩阵
	X_Array tran_X_Array();               // 稀疏矩阵转置
	X_Array operator +(X_Array &);        // 稀疏矩阵相加
	X_Array operator *(X_Array &);        // 稀疏矩阵相乘


};

// 以三元组形式键盘输入稀疏矩阵非零元素

template <class T>
void X_Array<T>::in_X_Array()
{
	int k,m,n;
	cout<<"输入行数 列数 非零元素个数:"<<endl;
	cin>>mm>>nn>>tt;
	bb=new B<T>[tt];
	cout<<"输入行号 列号 非零元素值:"<<endl;
	for(k=0;k<tt;k++)
	{
		cin>>m>>n>>bb[k].v;
		bb[k].i=m-1;
		bb[k].j=n-1;
	}
	pos=new int[mm];
	num=new int[mm];
	for(k=0;k<mm;k++)  //num向量初始化
		num[k]=0;      //初始化mm行的每行num都设为零
	for(k=0;k<tt;k++)
		num[bb[k].i]=num[bb[k].i]+1;  //提取每个非零元素的行号,出现行号的数组num值加1,当n个非零元素在同一行时,则加n次。
		pos[0]=0;
	for(k=1;k<mm;k++)       //构造pos向量
		pos[k]=pos[k-1]+num[k-1];  //pos[k]表示在稀疏矩阵第k行中第一个非零元素在数组B中的行号
		return;
}

//复制三元数组
template <class T>
void X_Array<T>::cp_X_Array(int m,int n,int t,B<T> b[])
{
	int k;
	mm=m;
	nn=n;
	tt=t;
	bb=new B<T>[tt];
	for(k=0;k<tt;k++)
	{
		bb[k].i=b[k].i-1;
		bb[k].j=b[k].j-1;
		bb[k].v=b[k].v;
	}
	pos=new int[mm];
	num=new int[mm];
	for(k=0;k<mm;k++)  //num向量初始化
		num[k]=0;      //初始化mm行的每行num都设为零
	for(k=0;k<tt;k++)
		num[bb[k].i]=num[bb[k].i]+1;  //提取每个非零元素的行号,出现行号的数组num值加1,当n个非零元素在同一行时,则加n次。
		pos[0]=0;
	for(k=1;k<mm;k++)       //构造pos向量
		pos[k]=pos[k-1]+num[k-1];  //pos[k]表示在稀疏矩阵第k行中第一个非零元素在数组B中的行号
		return;

}
// 由一般稀疏矩阵转换
template <class T>
void X_Array<T>::th_X_Array(int m,int n,T a[])
{
	int k,t=0,p,q;
	T d;
	for(k=0;k<m*n;k++)          //统计非零个数
		if(a[k]!=0) t++;  
	mm=m;nn=n;tt=t;
	bb=new B<T>[tt];
	k=0;
	for(p=0;p<m;p++)
		for(q=0;q<n;q++)
		{
			d=a[p*n+q];
			if(d!=0)             //非零元素
			{
				bb[k].i=p;
				bb[k].j=q;
				bb[k].v=d;
				k=k+1;
			}
		}
		pos=new int[mm];
		num=new int[mm];
		for(k=0;k<mm;k++)  //num向量初始化
			num[k]=0;      //初始化mm行的每行num都设为零
		for(k=0;k<tt;k++)
			num[bb[k].i]=num[bb[k].i]+1;  //提取每个非零元素的行号,出现行号的数组num值加1,当n个非零元素在同一行时,则加n次。
			pos[0]=0;
		for(k=1;k<mm;k++)       //构造pos向量
			pos[k]=pos[k-1]+num[k-1];  //pos[k]表示在稀疏矩阵第k行中第一个非零元素在数组B中的行号
			return;

}
// 按行输出稀疏矩阵
template <class T>
void X_Array<T>::prt_X_Array()
{
	int k,kk,p;
	for(k=0;k<mm;k++)                         //按行输出
	{
		p=pos[k];
		for(kk=0;kk<nn;kk++)                  //输出一行
			if((bb[p].i==k)&&(bb[p].j==kk))   //输出非零元素
			{
				cout<<setw(8)<<bb[p].v;p=p+1;
			}
			else
				cout<<setw(8)<<0;
		cout<<endl;
	}
	return;

}
// 稀疏矩阵转置
template <class T>
X_Array<T> X_Array<T>::tran_X_Array()
{
	X_Array<T> at;                                 //定义转置矩阵对象
	int k,p,q;
	at.mm=nn;
	at.nn=mm;
	at.tt=tt;
	at.bb=new B<T>[tt];
	k=0;
	for(p=0;p<nn;p++)                              //按列扫描所有非零元素
		for(q=0;q<tt;q++)
		{
			if(bb[q].j==p)                         //  将非零元素一次存放到转置矩阵的三列二维数组中               
			{
				at.bb[k].i=bb[q].j;
				at.bb[k].j=bb[q].i;
				at.bb[k].v=bb[q].v;
				k++;
			}
		}
		at.pos=new int[at.mm];
		at.num=new int[at.mm];
		for(k=0;k<at.mm;k++)
			at.num[k]=0;
		for(k=0;k<at.tt;k++)
			at.num[at.bb[k].i]=at.num[at.bb[k].i]+1;
		at.pos[0]=0;
		for(k=1;k<at.mm;k++)
			at.pos[k]=at.pos[k-1]+at.num[k-1];
		return (at);                                      //返回转置矩阵
}

// 稀疏矩阵相加
template <class T>
X_Array<T> X_Array<T>::operator+ (X_Array<T> &b)
{
	X_Array<T> c;
	B<T> *a;
	T d;
	int m,n,k,p;
	if((mm!=b.mm)||(nn!=b.nn))
		cout<<"不能相加!"<<endl;
	else
	{
		a=new B<T>[tt+b.tt];                         //临时申请一个三列二维数组空间
		p=0;
		for(k=0;k<mm;k++)                            //逐行处理
		{
			m=pos[k];n=b.pos[k];
			while((bb[m].i==k)&&(b.bb[n].i==k))        //行号相同
			{
				if(bb[m].j==b.bb[n].j)                 //列号相同则相加
				{
					d=bb[m].v+b.bb[n].v;
					if(d!=0)                           //相加后非零
					{
						a[p].i=k;a[p].j=bb[m].j;
						a[p].v=d;p=p+1;
					}
					m=m+1;n=n+1;
				}
				else if(bb[m].j<b.bb[n].j)            //列号不同则复制列号小的一项
				{
					a[p].i=k;a[p].j=bb[m].j;
					a[p].v=bb[m].v;p=p+1;
					m=m+1;

				}
				else                                 //列号不同复制另一项
				{
					a[p].i=k;a[p].j=b.bb[m].j;
					a[p].v=b.bb[m].v;p=p+1;
					n=n+1;

				}
			}
			while(bb[m].i==k)                       //复制矩阵中本行剩余的非零元素
			{
				a[p].i=k;a[p].j=bb[m].j;
				a[p].v=bb[m].v;p=p+1;
				m=m+1;

			}
			while(b.bb[n].i==k)                    //复制另一矩阵中本行剩余的非零元素
			{
				a[p].i=k;a[p].j=b.bb[m].j;
				a[p].v=b.bb[m].v;p=p+1;
				n=n+1;

			}
		}
		c.mm=mm;c.nn=nn;c.tt=p;
		c.bb=new B<T>[p];                          //申请一个三列二维数组空间
		for(k=0;k<p;k++)                           //复制临时三列二维数组空间中的元素
		{
			c.bb[k].i=a[k].i;
			c.bb[k].j=a[k].j;
			c.bb[k].v=a[k].v;
		}
		delete a;                                    //释放临时三列二维数组空间
		c.pos=new int[c.mm];
		c.num=new int[c.mm];
		for(k=0;k<c.mm;k++)
			c.num[k]=0;
		for(k=0;k<c.tt;k++)
			c.num[c.bb[k].i]=c.num[c.bb[k].i]+1;
		c.pos[0]=0;
		for(k=1;k<c.mm;k++)
			c.pos[k]=c.pos[k-1]+c.num[k-1];

	}
	return c;
}
template <class T>
X_Array<T> X_Array<T>::operator* (X_Array<T> &b)
{
	X_Array<T> cc;
	int k,m,n,p,t;
	T *c;                  //定义乘积矩阵
	if(nn!=b.mm)
		cout<<"两矩阵无法相乘!"<<endl;
	else
	{
		c=new T[mm*b.nn];  //申请乘积矩阵的临时空间
		k=0;
		for(m=0;m<mm;m++)     
		{
			for(n=0;n<b.nn;n++)
			{
				c[k]=0;k=k+1;  //乘积矩阵元素初始化为零
			}
		}
		for(m=0;m<tt;m++)     //对于左矩阵中的每一个非零元素
		{
			k=bb[m].j;        //左矩阵中非零元素的列值K
			n=b.pos[k];       //右矩阵中行号与K相同的第一个非零元素的位置
			t=b.pos[k]+b.num[k];//右矩阵中行号与k相同的最后一个非零元素的位置
			while(n!=t)
			{
				p=bb[m].i*b.nn+b.bb[n].j;//在乘积矩阵中的位置
				c[p]=c[p]+bb[m].v*b.bb[n].v;//累加非零元素的乘积
				n=n+1;
			}

		}
		cc.th_X_Array(mm,b.nn,c); //由一般的稀疏矩阵转换成用三列二维数组表示
		delete c;                 //释放乘积矩阵的临时空间
	}
	return cc;
}



2.实例应用:

#include "test2.h"
#include<stdlib.h>
int main()
{
	B<double> a[8]={{1,3,3.0},{1,8,1.0},{3,1,9.0},{4,5,7.0},{5,7,6.0},{6,4,2.0},{6,6,3.0},{7,3,5.0}};
	X_Array<double> x,y,z,xt,c;
	x.cp_X_Array(7,8,8,a);
	cout<<"输出稀疏矩阵X:"<<endl;
	x.prt_X_Array();
	xt=x.tran_X_Array();

	cout<<"输出稀疏矩阵x的转置xt:"<<endl;
	xt.prt_X_Array();
	y.in_X_Array();
	cout<<"输出稀疏矩阵y:"<<endl;
	y.prt_X_Array();
	z=x+y;
	cout<<"输出稀疏矩阵z=x+y"<<endl;
	z.prt_X_Array();
	c=x*xt;
	cout<<"输出稀疏矩阵c=x*y"<<endl;
	c.prt_X_Array();
	system("pause");
	return 0;
}


3.实验结果:

 

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值