zoukankan      html  css  js  c++  java
  • 稀疏矩阵的转置运算

      (1)设m*n 矩阵中有t 个非零元素且t远小于m*n,这样的矩阵称为稀疏矩阵。很多科学管理及工程计算中,常会遇到阶数很高的大型稀疏矩阵。如果按常规分配方法,顺序分配在计算机内,那将是相当浪费内存的。为此提出另外一种存储方法,仅仅存放非零元素。但对于这类矩阵,通常零元素分布没有规律,为了能找到相应的元素,所以仅存储非零元素的值是不够的,还要记下它所在的行和列。于是采取如下方法:将非零元素所在的行、列以及它的值构成一个三元组(i,j,v),然后再按某种规律存储这些三元组,这种方法可以节约存储空间。

      将三元组按行优先的顺序,同一行中列号从小到大的规律排列成一个线性表,称为三元组表,采用顺序存储方法存储该表。如下图:

     可以将其改写成如下的三元组的形式,同时存储器行、列和值,如下:

    i

    j

    v

    1

    2

    12

    1

    3

    9

    3

    1

    -3

    3

    6

    14

    4

    3

    24

    5

    2

    18

    6

    1

    15

    6

    4

    -7

    对应的三元组的数据结构可以写成如下形式的数据结构:

    //定义三元组的数据结构类型
    typedef struct{
    	int i,j;		//非零元素的行和列
    	ElemType e;		//非零元素的值
    }Triple;
    
    //三元组表的存储类型
    typedef struct{
    	int mu,nu,tu;				//矩阵的行、列以及非零元的个数
    	Triple data[MAXSIZE+1];	    //三元组表
    }Matrix;
    

     (2)、矩阵的转置

    要做到转置要做到三点

    ①、将矩阵的行列值互换

    ②、将每个三元组的i、j互换

    ③、重新排列三元组

    如下图:

      

    方法一:

      ①、将矩阵A的行列转化为矩阵B的列和行

      ②、以B的行(col)为标准依次遍历三元组的列值(j)的值,即矩阵A的第一列的元素必在B的第一行中,依次赋值。

      程序如下:

    int TransposeSMatrix(Matrix M,Matrix *X)
    {
    	int col,p,q;
    	//设置转置矩阵的结构
    	X->mu=M.nu;
    	X->nu=M.mu;
    	X->tu=M.tu;
    	//矩阵中有非零元素才开始去完成转置工作,否则没有意义
    	if(X->tu)
    	{
    		q=1;
    		//遍历每一列的非零元素
    		for(col=1;col<=M.nu;col++)
    			//扫描三元组中非零元素的个数
    			for(p=1;p<=M.tu;p++)
    				if(M.data[p].j==col)	//若找到该列的非零元素,开始对该元素的行列转换
    				{
    					X->data[q].i=M.data[p].j;
    					X->data[q].j=M.data[p].i;
    					X->data[q].e=M.data[p].e;
    					//继续去对第二个元素进行变化、
    					q++;
    				}
    	}
    	return OK;
    }
    

     方法二:

       易看出方法一的时间复杂度主要体现在两次循环上( O(nu*tu)  ),当非零元的个数过多的时候(即与mu*nu是同一个数量级的时候),算法的复杂度变为了(o(mu*nu2),虽然此方法在空间上节省了存储空间,但在时间上花费了太大的比重。方法二设置了两个数组num和cpot,num[col]代表矩阵A的每一列的非零元素的个数,cpot[col]表示矩阵A中第col列第一个非零元素的在B对应的三元组的位置,即

      cpot[1]=1

      cpot[col]=cpot[col-1]+num[col-1]     (2<=col<=A.nu)

     对应的矩阵A的num和cpot值如下

     

    对应的程序如下所示:

    int FastTransposeSMatrix(Matrix M,Matrix *X)
    {
    	int col,k,p,q;
    	int cpot[10],num[10];
    	X->mu=M.nu;
    	X->nu=M.mu;
    	X->tu=M.tu;
    	//矩阵中有非零元素才开始去完成转置工作,否则没有意义
    	if(X->tu)
    	{
    		//num代表每一行非零元的个数,初始化为0
    		for(col=1;col<=M.tu;col++)
    			num[col]=0;
    
    		//计算每一列中非零元的个数
    		for(k=1;k<=M.tu;k++)
    			num[M.data[k].j]++;
    
    		//初始化cpot为1 cpot代表矩阵M中第col列的第一个非零元素的转置后矩阵X.data的位置
    		cpot[1]=1;
    		for(col=2;col<=M.nu;col++)
    			cpot[col]=cpot[col-1]+num[col-1];
    		
    		for(p=1;p<=M.tu;p++)
    		{
    			col=M.data[p].j;
    			q=cpot[col];
    			X->data[q].i=M.data[p].j;
    			X->data[q].j=M.data[p].i;
    			X->data[q].e=M.data[p].e;
    			cpot[col]++;
    		}
    	}
    	return OK;
    }
    

    完整程序如下:

      

    #include<stdio.h>
    #define OK 1
    #define MAXSIZE 100
    typedef int ElemType;
    
    //定义三元组的数据结构类型
    typedef struct{
    	int i,j;		//非零元素的行和列
    	ElemType e;		//非零元素的值
    }Triple;
    
    //三元组表的存储类型
    typedef struct{
    	int mu,nu,tu;				//矩阵的行、列以及非零元的个数
    	Triple data[MAXSIZE+1];	    //三元组表
    }Matrix;
    
    int TransposeSMatrix(Matrix M,Matrix *X)
    {
    	int col,p,q;
    	//设置转置矩阵的结构
    	X->mu=M.nu;
    	X->nu=M.mu;
    	X->tu=M.tu;
    	//矩阵中有非零元素才开始去完成转置工作,否则没有意义
    	if(X->tu)
    	{
    		q=1;
    		//遍历每一列的非零元素
    		for(col=1;col<=M.nu;col++)
    			//扫描三元组中非零元素的个数
    			for(p=1;p<=M.tu;p++)
    				if(M.data[p].j==col)	//若找到该列的非零元素,开始对该元素的行列转换
    				{
    					X->data[q].i=M.data[p].j;
    					X->data[q].j=M.data[p].i;
    					X->data[q].e=M.data[p].e;
    					//继续去对第二个元素进行变化、
    					q++;
    				}
    	}
    	return OK;
    }
    
    int FastTransposeSMatrix(Matrix M,Matrix *X)
    {
    	int col,k,p,q;
    	int cpot[10],num[10];
    	X->mu=M.nu;
    	X->nu=M.mu;
    	X->tu=M.tu;
    	//矩阵中有非零元素才开始去完成转置工作,否则没有意义
    	if(X->tu)
    	{
    		//num代表每一行非零元的个数,初始化为0
    		for(col=1;col<=M.tu;col++)
    			num[col]=0;
    
    		//计算每一列中非零元的个数
    		for(k=1;k<=M.tu;k++)
    			num[M.data[k].j]++;
    
    		//初始化cpot为1 cpot代表矩阵M中第col列的第一个非零元素的转置后矩阵X.data的位置
    		cpot[1]=1;
    		for(col=2;col<=M.nu;col++)
    			cpot[col]=cpot[col-1]+num[col-1];
    		
    		for(p=1;p<=M.tu;p++)
    		{
    			col=M.data[p].j;
    			q=cpot[col];
    			X->data[q].i=M.data[p].j;
    			X->data[q].j=M.data[p].i;
    			X->data[q].e=M.data[p].e;
    			cpot[col]++;
    		}
    	}
    	return OK;
    }
    
    //创建系数矩阵,用三元组法表示
    void Create(Matrix *M)
    {
    	int i;
    	printf("请分别输入非零元素的行(mu)、列(nu)以及非零元素的个数(ti):");
    	scanf("%d %d %d",&M->mu,&M->nu,&M->tu);
    	printf("请按以下格式输入非零元素(行 列 元素值):
    ");
    	for(i=1;i<=M->tu;i++)
    		scanf("%d %d %d",&M->data[i].i,&M->data[i].j,&M->data[i].e);
    }
    
    //以矩阵的形式输出三元组表示存储的稀疏矩阵
    void print(Matrix M)
    {	
    	
    	int i,j,k;
    	//二维数组初始化
    	int a[10][10]={0};
    	for(k=1;k<=M.tu;k++)
    	{
    		i=M.data[k].i;
    		j=M.data[k].j;
    		a[i][j]=M.data[k].e;
    	}
    	printf("Matrix is : 
    ");
    	for(i=1;i<=M.mu;i++)
    	{
    		for(j=1;j<=M.nu;j++)
    			printf("%4d",a[i][j]);
    		printf("
    ");
    	}
    }
    
    void main()
    {
    	Matrix M,X;
    	Create(&M);
    	print(M);
    	FastTransposeSMatrix(M,&X);
    	print(X);
    }	
    

     运行结构如下:

      

  • 相关阅读:
    与答辩有关资料
    SpringBoot技术优点
    【知识库】-简单理解CrudRepository接口中的方法
    【知识库】-通俗理解OAuth2.0协议用于第三方登陆
    毕业设计介绍所用
    JavaWeb_(视频网站)_七、推荐模块1
    JavaWeb_(视频网站)_六、分页模块1
    JavaWeb_(视频网站)_五、视频模块2 辅助功能
    JavaWeb_(视频网站)_五、视频模块1 视频上传
    JavaWeb_(视频网站)_四、博客模块2
  • 原文地址:https://www.cnblogs.com/helloworldcode/p/6885949.html
Copyright © 2011-2022 走看看