学习日志---矩阵表示及特殊矩阵压缩

矩阵类:二维数组实现!!

每一行看成一个一维数组,在放入几个集合里面即可;

用到random类,可以生产随机数,括号里是最大值;

矩阵类:
public class MyMatrix {
   
	int[][] matrix ;//矩阵数组
	Random random =new Random() ;//随机数对象

	//默认的构造方法,生成3*3的矩阵
	public MyMatrix()
	{
	        //默认是3*3矩阵
		matrix = new int[3][3];
		//初始矩阵
		for(int i=0;i<matrix.length;i++)
		{
			for(int j=0;j<matrix[i].length;j++)
			{
				matrix[i][j]=random.nextInt(100);
			}
		}
	}

	//生成方阵的构造方法
	public MyMatrix(int n)
	{
	    matrix = new int[n][n];
	    //初始矩阵
		for(int i=0;i<matrix.length;i++)
		{
			for(int j=0;j<matrix[i].length;j++)
			{
				matrix[i][j]=random.nextInt(100);
			}
		}
	}

	//生成一个m*n的矩阵。
	public MyMatrix(int m,int n)
	{
		matrix = new int[m][n];
		//初始矩阵
		for(int i=0;i<matrix.length;i++)
		{
			for(int j=0;j<matrix[i].length;j++)
			{
				matrix[i][j]=random.nextInt(100);
			}
		}
	}

	//根据已知二维数组,生成矩阵
	public MyMatrix(int[][] matrix)
	{
		this.matrix = matrix;
	}

	//返回矩阵数组
	public int[][] getMatrix()
	{
		return this.matrix;
	}

	//打印矩阵
	public void print()
	{
		for(int i=0;i<matrix.length;i++)
		{
			for(int j=0;j<matrix[i].length;j++)
			{
				System.out.print(matrix[i][j]+" ");
			}
			System.out.println();
		} 
	}

	//转置矩阵
	public MyMatrix transport()
	{
	    //行变列
		int m = matrix[0].length;
		//列变行
		int n = matrix.length;

		MyMatrix transMatrix = new MyMatrix(m,n);
		//初始化
		//这里遍历新的矩阵,把原矩阵对称点放置进来
		for(int i=0;i<transMatrix.matrix.length;i++)
		{
			for(int j=0;j<transMatrix.matrix[i].length;j++)
			{
				transMatrix.matrix[i][j] = matrix[j][i];
			}
		}
		return transMatrix; 
	}

	//判断矩阵是否是上三角矩阵
	public boolean isUpTriangle()
	{
	   for(int i=1;i<matrix.length;i++)
	   {
		   for(int j=0;j<i;j++)
		   {
			   if(matrix[i][j]!=0)
			   {
				   return false;
			   }
		   }
	   }
	   return true;
	}

	//判断是否是下三角矩阵
    public boolean isDownTriangle()
    {
    	for(int i=0;i<matrix.length;i++)
    	{
    		for(int j=matrix[i].length-1;j>i;j--)
    		{
    		   if(matrix[i][j]!=0)
  			   {
  				   return false;
  			   }
    		}
    	}
    	return true;
    }
    
    //判断是否是对称矩阵
    public boolean isSynmetry()
    {
       for(int i=1;i<matrix.length;i++)
  	   {
  	          //这里可以j<i即可,因为只查看一半即可,这样会重复
  		  for(int j=0;j<matrix[i].length;j++)
  		  {
  			  if(matrix[i][j]!=matrix[j][i])
  			  {
  				  return false;
  			  }
  		  }
  	   }
  	   return true;
    }
    
    //矩阵求和
    public void add(MyMatrix b)
    {
       int m = b.matrix.length;
       int n = b.matrix[0].length;
       if(m!=matrix.length||n!=matrix[0].length)
       {
    	   System.out.println("矩阵类型不相同,无法相加!");
       }
       else
       {
    	   for(int i=0;i<matrix.length;i++)
   		   {
   			 for(int j=0;j<matrix[i].length;j++)
   			 {
   				matrix[i][j]+=b.matrix[i][j];
   			 }
   			 
   		   } 	 
       }
    }
}

对称矩阵的压缩算法:

把下三角或者上三角存在一维数组中;

把二维数组中的数据三角式的一行一行的存在一维数组中,取出时,对应n*n循环,找出一维数组中的位置对应数据存在二维数组中,即为二维数组。

//对称矩阵类压缩
public class SynmeMatrix {
  
        //a用来存储矩阵的副本
	double [] a;//矩阵元素
	int n; //矩阵的阶数;
	int m; //一维数组的个数

	public SynmeMatrix(int n)
	{
		//需要保持的元素个数是m=n*(n+1)/2 ;
		//这里要注意m的大小
		m = n*(n+1)/2 ;
		a = new double[m];
		this.n = n;
	}
	//通过一个二维数组来初始化
	public void evaluate(double[][] b)
	{
	  	int k=0;
	  	for(int i=0;i<n;i++)
	  	{
	  		for(int j=0;j<n;j++)
	  		{
	  		   if(i>=j)
	  		   {
	  		      //System.out.println("a["+k+"]="+b[i][j]);
                              //把b中的数据存到a这个副本中
                              //因为是对称阵,三角式的一行一行的存里面,这样起到节省空间的作用
	  			  a[k++]=b[i][j]; //只保存下三角元素
	  		   }
	  		}
	  	}

	}

	//通过一个一维数组来初始化,那么这个一维数组就是对称矩阵元素的副本
        //b为副本,传进来,因此与a相等
	public void evaluate(double[] b)
	{
		for(int k=0;k<m;k++)
		{
			a[k]= b[k];
		}
	}

	//对称矩阵相加
	public SynmeMatrix add(SynmeMatrix b)
	{
	   SynmeMatrix t = new SynmeMatrix(n);
	   int k;
	   for(int i=1;i<=n;i++)
	   {
		   for(int j=1;j<=n;j++)
		   {
                           //k是指副本中的位置,根据i和j找到对应该位置的值,两个synmeMatrix相同,因此具有的规则一样
			   if(i>=j)
			   {
				   k= i*(i-1)/2+j-1;
			   }
			   else
			   {
				   k= j*(j-1)/2+i-1;
			   }
			   t.a[k] = a[k]+b.a[k];
		   }
	   }
	   return t;
	}

	//打印对称矩阵
	public void print()
	{
		   int k;
                   //存的是副本,是一维数组,因此可以从二维数据的位置坐标找到一位数组中对应的位置的数据,即为二维数组中的数据
		   for(int i=1;i<=n;i++)
		   {
			   for(int j=1;j<=n;j++)
			   {
				   if(i>=j)
				   {
					   k= i*(i-1)/2+j-1;
				   }
				   else
				   {
					   k= j*(j-1)/2+i-1;
				   }
				   System.out.print(" "+a[k]);
			   }
			   System.out.println();
		   }
	}
}

稀疏矩阵压缩算法:

只存储数据的位置和元素,用三元组存储;

三元组的存储结构可以用一维数组或者链表结构;

这里用到了前面的MyVector集合存储非零数据信息;

下面是用数组的结构建立的系数矩阵;

//三元组类,非零元素的信息,行、列、数据
//每个节点都是一个数据点
public class Three {

	public int row;
	public int col;
	public double value;

	public Three(int r,int c,double v)
	{
		this.row = r;
		this.col = c;
		this.value = v;
	}

	public Three()
	{
		this(0,0,0.0);
	}

}

//稀疏矩阵类
//需要行和列,以及非零元素个数和位置即可
public class SpaMatrix {
   
	int rows; //行数
	int cols; //列数
	int dNum;//非零元素个数
	//v是存非零元素的集合,v中的顺序不重要,因为都是相互独立的
    MyVector v;
    
    SpaMatrix(int max)
    {
    	rows = cols = dNum=0;
    	v = new MyVector(max);
    }
    
    //根据用户传来的三元组数组,来初始化矩阵
    public void evaluate(int r,int c,int d,Three[] item)throws Exception
    {
    	this.rows = r;
    	this.cols = c;
    	this.dNum = d;
    	for(int i=0;i<d;i++)
    	{
    		v.add(i, item[i]);
    	}
    }
    
    //稀疏矩阵的转置
    public SpaMatrix transport()throws Exception
    {
        //稀疏矩阵只需要非零元素的位置和数据,因此构建时传入v的大小即可;
    	SpaMatrix a = new SpaMatrix(v.size());
    	a.rows = this.cols;
    	a.cols = this.rows;
    	a.dNum = this.dNum;
    
    	for(int i=0;i<dNum;i++)
    	{
    		Three t = (Three)v.get(i);
    	    a.v.add(i, new Three(t.col,t.row,t.value));
    	}
    	return a;
    }
    
    //打印稀疏矩阵的方法
    public void print() throws Exception
    {
    	System.out.println("矩阵的行数:"+this.rows);
    	System.out.println("矩阵的列数:"+this.cols);
    	System.out.println("非零元素个数:"+this.dNum);
    
    	System.out.println("矩阵三元组为:");
    	for(int i=0;i<dNum;i++)
    	{
    	   System.out.println("a<"+((Three)v.get(i)).row+","+((Three)v.get(i)).col+">="+((Three)v.get(i)).value);
    	}
    }
}

也可用链表结构实现:

图片不清楚,文字说明:每个节点都存位置信息,数据信息和下一个节点位置,这种方法不是很好。

数组与链式结构相结合:

图片不清楚,文字说明:这种方法比较好的地方就是很清晰,数组记录行,后面的链表记录该行内列的信息,依次连接。

时间: 2024-10-29 03:16:05

学习日志---矩阵表示及特殊矩阵压缩的相关文章

webpack2学习日志

webpack说容易也容易,说难也难,主要还是看个人,想学到什么样的程度,很多公司可能要求仅仅是会用就行,但是也有一些公司要求比较高,要懂一些底层的原理,所以还是要花一些时间的,看个人需求.这篇仅仅是做了一些总结,都是来自官网,便于复习. 一,先理解webpack的概念: 官网上:webpack 是一个现代 JavaScript 应用程序的模块打包器(module bundler).当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用

支配树学习日志

支配树 学习日志 给定一张有向图 $G=(V, E)$,其中 $\lvert V \rvert=n, \lvert E \rvert=m$,以及根 $r \in V$. 我们称顶点 $x\ (x \ne r)$ 可达,当且仅当存在一条从 $r$ 到 $x$ 的路径. 对于 $x \ne r$ 且可达的 $x$,如果 $y \ne x$,且删去 $y$ 后 $x$ 不可达,那么就说 $y$ 支配 $x$.特别地,$r$ 一定支配 $x$. 不可达的点的支配点没有定义,因此我们不妨设 $G$ 的所有

winform学习日志(二十三)---------------socket(TCP)发送文件

一:由于在上一个随笔的基础之上拓展的所以直接上代码,客户端: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using Sys

Linux学习日志2-vim使用基础

vim是linux操作系统下的一个文本编辑工具,功能非常强大,但刚学习起来比较复杂.vim的所有功能要讲明白得有几百页,在这里只是记录一下vim的一些基本用法. 首先vim打开文件的三种方式: vim +# xxx(#是数字):表示打开xxx文件并将光标定位到指定行. vim -o xx1 xx2 xx3:表示同时打开三个文件,垂直分割显示 vim -O xx1 xx2 xx3:表示同时打开三个文件,水平分割显示 多个文件间跳转:键入ctrl+w后:→向左.←向右.↑向上.↓向下 vim打开文件

Linux学习日志day1——无人值守系统安装DHCP+TFTP+PXE+Kickstar

Linux学习日志day1--无人值守批量系统远程网络安装(DHCP+TFTP+PXE+Kickstar)                                         --作者:江信瀚 服务器环境介绍: 主机名:workstation.example.com 关闭SElinux以及防火墙 虚拟机:VMware(关闭了VMware的DHCP服务) 网卡配置: 静态IP获取! IPV6全部都删除,因为根本用不到 子网IP可以在VMware中设置 8.8.8.8是谷歌的DNS服务器

Cocos2d-x 3.1.1 学习日志4--cocos2d-x解决中文乱码问题的几种办法

做个打飞机的游戏,由于版本太新,网上基本没有教教程,我的版本是cocos2d-x 3.1.1的,今天遇到cocos2dx中中文乱码的问题.无奈只好Google百度寻求答案,明白了这个问题的缘由.因为cocos2d-x内部是以utf8处理文本的,而VS直接输入时文本编码为GBK,如果添加L标志,则为Unicode编码. 解决这个问题有三种办法: 将源代码文件保存为utf8编码,不过由于编译器的问题,这种方式会导致很多无法预测的问题 将字符串用utf8编码集中存到一文件中,然后用代码读取这些字符串来

Cocos2d-x 3.1.1 学习日志3--C++ 初始化类的常量数据成员、静态数据成员、常量静态数据成员

有关const成员.static成员.const static成员的初始化: 1.const成员:只能在构造函数后的初始化列表中初始化 2.static成员:初始化在类外,且不加static修饰 3.const static成员:类只有唯一一份拷贝,且数值不能改变.因此,可以在类中声明处初始化,也可以像static在类外初始化 #include <iostream> using std::cout; using std::endl; class base { public: base(int

SQL 学习日志01

查看一个数据库的所有表: Select TABLE_NAME FROM 数据库名称.INFORMATION_SCHEMA.TABLES Where TABLE_TYPE='BASE TABLE' (select * from 表名 where 条件) 查看一张表的表结构: sp_help table_name(表名)  获取的信息比较全 sp_columns table_name(表名) 创建数据库: use master go create database test01(数据库名) 删除数据

SQL 学习日志02

SQL数据类型 1.字符类型 char   --定长字符数据   如 char(12)  这字段就会占用12字节的空间,无论这个字段只填写了2个字节.一般在可确定这字段长度时选用,如sex字段(因只有男和女两项可选)就可用 char(2). varvhar   --可变长字符数据  如varchar(50) 这字段最大只能填写50字节,按实际填写的字节存储.一般在不确定这字段长度时使用,如 Smail字段(因邮箱的长度不确定) 就可用varchar(50). text    --用来存储大量非统