必威体育Betway必威体育官网
当前位置:首页 > IT技术

稀疏矩阵

时间:2019-08-17 10:12:12来源:IT技术作者:seo实验室小编阅读:63次「手机版」
 

稀疏矩阵

一、稀疏矩阵的定义

1、稀疏矩阵的概念

   矩阵:矩阵是一个具有m行*n列的数表,共包含m*n个元素(元素),每个元素处在确定行和列的交点位置上,它与一对行号和列号唯一对应。当一个矩阵中的行数和列数相同时,即m=n时,则称为n阶矩阵或方阵。

  稀疏矩阵:一般定义为其矩阵中非零元素的个数远远小于零元素的个数。

2、稀疏矩阵的三元组线性表表示

  在计算机中存储矩阵的一般方法是采用二维数组,其优点是可以随机地访问到任何一个元素,也就是说,访问任一元素的时间都相同,每个元素的存储位置是通过对下标的简单计算而得到的,因此能够较容易地实现矩阵的各种运算,如转置运算、加法运算、乘法运算等。但对于稀疏矩阵来说,采用二维数组的存储方法既浪费大量的存储空间用来存放零元素,又要在运算中花费大量的时间来进行零元素的无效计算,显然是不可取的。一种较好的方法是:只考虑存储占元素中极少数的非零元素。

  对于稀疏矩阵中的每个非零元素,可用它所在的行号、列号以及元素值这3个数据即三元组(i,j,aij)来表示。若把一个稀疏矩阵中的所有三元组依次按照行号为主序,列号为辅序进行升序排列,就构成了一个表示稀疏矩阵的三元组线性表,并且该表是按行、列号有序的。

  稀疏矩阵采用三元组线性表表示后,可以使用顺序或链接方式存储,从而比采用二维数组存储要大大地节省存储空间和运算时间。

3、三元组的类型定义

   在稀疏矩阵的三元组线性表中,每个元素为一个表示非0元素的三元组,它包括行号,列号和值,假定分别用标识符row,col和val表示,并假定用标识符Triple表示三元组类,则定义为:

public class Triple implements Comparable {
	
	int row;                                        //行号
	int col;                                        //列号
	double val;                                     //元素值
	
	public Triple(int row, int col, double val) {   //构造方法
		super();
		this.row = row;
		this.col = col;
		this.val = val;
	}

	public boolean equals(Object obj) {              //定义比较两元素相同的方法
		Triple t=(Triple)obj;
		if((this.row==t.row)&&(this.col==t.col))
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	public String toString() {                      //三元组的字符串输出格式
		return "("+row+","+col+","+val+")";
	}
	
	public int compareTo(Object obj) {                //按列号比较两元素的大小
		Triple  t=(Triple)obj;
		if(this.row>t.row)
		{
			return 1;
		}
		else if(this.row<t.row)
		{
			return -1;
		}
		else
		{
			//执行到此时必然是this.row==t.row 为真
			if(this.col>t.col)
			{
				return 1;
			}
			else if(this.col<t.col)
			{
				return -1;
			}
			else
			{
				return 0;
			}
		}
	}
}

4、稀疏矩阵的类型定义

在稀疏矩阵的类型中,其数据成员应当包括稀疏矩阵的总行数,总列数,以及一个存储非零元素的三元有序线性表,假定他们的标识符分别用rows,cols和terms表示;除数据成员外,还应当包含一些对矩阵运算的方法,如转置方法、矩阵相加方法、输出矩阵方法等。假定稀疏矩阵类型用SparseMatrix表示,下面给出它的具体定义:

   注:SortedList类,sequenceSortedList类,List接口等来自线性表一文。

public class SparseMatrix {
	
	//稀疏矩阵类的定义
	private int rows;              //稀疏矩阵的行数
	private int cols;              //稀疏矩阵的列数
	private SortedList terms;      //保存稀疏矩阵的三元组有序线性表
	public SparseMatrix(int r,int c,List list)
	{
		rows=r;
		cols=c;
		terms=new SequenceSortedList(list);  //利用线性表list构造有序表
	}
	
	//输出稀疏矩阵的行列数和三元组有序线性表表示
	public void outputMatrix()
	{
		System.out.println("稀疏矩阵的行数和列数:"+rows+","+cols);
		terms.forward();
	}
	
	//转置
	public SparseMatrix transpose()
	{
		//定义和创建一个转置矩阵B的独享sm,它的行数为矩阵A的列数,列数为当前矩阵A
		//的行数,并用空的顺序或链接线性表初始化sm的三元组有序线性表
		SparseMatrix sm=new SparseMatrix(cols,rows,new SequenceList());
		//若当前矩阵是零矩阵(即非零元素的个数为0的矩阵),则转换完毕返回
		if(terms.size()==0)
		{
			return sm;
		}
		//扫描当前矩阵中的三元组线性表中的每个元素,构成转置元素而插入到sm的表中
		for(int i=1;i<=terms.size();i++)      //用i扫描每个被转换的元素
		{
			Triple x=(Triple)terms.value(i);  //读取一个三元组元素到x中
			sm.terms.insert(new Triple(x.col,x.row,x.val));//按值插入新元素
		}
		//返回根据当前矩阵进行转置运算后而得到的转置矩阵
		return sm;
		
	}
	
	//加法
	public SparseMatrix sparseAdd(SparseMatrix sm)
	{
		//进行当前稀疏矩阵this和参数矩阵sm的加法运算,返回运算结果
		//若两个矩阵尺寸不同,则给出错误信息并停止运行
		if((rows!=sm.rows)||(rows!=sm.cols))
		{
			System.out.println("两个矩阵的尺寸不同,不能相加!");
			System.exit(1);
		}
		//定义和创建一个保存运算结果的稀疏矩阵tm,它的行,列数与当前矩阵相同
		//所采用的三元组线性表可以为顺序表,也可以外链接表
		SparseMatrix tm=new SparseMatrix(cols,rows,new SequenceList());
		//若两个矩阵均为零矩阵,则无须计算返回tm
		if((terms.size()==0&&(sm.terms.size()==0)))
		{
			return tm;
		}
		//定义整型变量i1和i2,分别表示待扫描到的两个加数线性表中的元素序号
		int i1=1,i2=1;   //初始值为1,各自指示三元组线性表中的第1个元素
		//当两个加数的三元组有序线性表同时不为空时的处理过程
		while(i1<=this.terms.size()&&i2<=sm.terms.size())
		{
			Triple x1=(Triple)this.terms.value(i1);    //取出this中的元素值到x1
			Triple x2=(Triple)sm.terms.value(i2);      //取出sm中的元素值到x2
			if(x1.compareTo(x2)<0)                     //因x1较小,将x1插入到tm的有序表表尾
			{
				tm.terms.add(x1, tm.terms.size()+1);
				i1++;                                  //为扫描this中的下一个三元组元素做准备
			}
			else if(x1.compareTo(x2)>0)                //因x2较小,将x2插入到tm的表尾
			{
				tm.terms.add(x2, tm.terms.size()+1);
				i2++;                                  //将扫描sm中的下一个元素
			}                                
			else	            //此时两个元素的行列相同若两值之和不为0则新元素插入表尾
			{
				double y=x1.val+x2.val;
				if(Math.abs(y)>1.0E-6)                 //判定0条件为避免出现误差而采用
				{
					Triple x3=new Triple(x1.row,x1.col,y);
					tm.terms.add(x3,tm.terms.size()+1);
				}
				i1++;
				i2++;                                  //两元素合并后,i1和i2均须后移
			}
		}
		//将this中的剩余三元组元素依次插入到tm的三元组有序线性表的表尾
		while(i1<=this.terms.size())
		{
			tm.terms.add(this.terms.value(i1), tm.terms.size()+1);
			i1++;
		}
		//将sm中的剩余三元组元素依次插入到tm中的三元组有序线性表的表尾
		while(i2<=sm.terms.size())
		{
			tm.terms.add(sm.terms.value(i2), tm.terms.size()+1);
			i2++;
		}
		return tm;                               //返回this和sm的加运算的结果矩阵tm
	}
}

相关阅读

分享到:

栏目导航

推荐阅读

热门阅读