内容:
编写程序使用三元组表实现稀疏矩阵的按列转置操作。
步骤:
1.算法分析:
进行程序设计前,要对稀疏矩阵的一些知识进行必要的解释。设m*n矩阵中有t个非零元素且t<<m*n,这样的矩阵称为稀疏矩阵。可以看出,稀疏矩阵的非零元素是很少的,所以如果将稀疏矩阵进行常规存储会存在浪费大量内存的现象,而且在很多科学计算中,常常会遇到很多阶数很高的的大型稀疏矩阵。
正是因为上述原因,所以我们采用如下方法存储:将非零元素所在的行、列以及它的值构成一个三元组(i,j,v),然后再按某种规律存储这些三元组,存储后,还需要进行一些简单的操作,比如稀疏矩阵的转置,即引出了本问题。
例如下列矩阵:
改为三元组表为:
i | j | v | |
1 | 1 | 1 | 15 |
2 | 1 | 4 | 22 |
3 | 1 | 6 | -15 |
4 | 2 | 2 | 11 |
5 | 2 | 3 | 3 |
6 | 3 | 4 | 6 |
7 | 5 | 1 | 91 |
A的转置成B为:
所以按照上述的思路,求出A的转置是B,下面给出B的三元组进行对比:
i | j | v | |
1 | 1 | 1 | 15 |
2 | 1 | 5 | 91 |
3 | 2 | 2 | 11 |
4 | 3 | 2 | 3 |
5 | 4 | 1 | 22 |
6 | 4 | 3 | 6 |
7 | 6 | 1 | -15 |
经过上述过程,得出了程序的基本思路,即定义一个三元组表,用户输入三元组表,但还需要设置一个结束标志,不妨设为(-1,-1,-1)。这样就能得到用户想要转化的三元组表。下面就是转置部分,将其按a的列序转置,并扫描整个三元组表,然后将A中的行列转换为列行赋值到B的三元组中的行列中。并且每个转换的值不发生改变。这里还需要注意一点,采用三元组表压缩存储稀疏矩阵,实现矩阵的转置时,注意我们得到的转置矩阵的三元组表是要按一行一行存放且每行中的元素是按列号从小到大的规律顺序存放。为了运算方便,矩阵的行列都从1算起,三元组表data也从1单元算起。
基于以上分析,我们可以设计出大概的思路:
程序中设计了三个函数:
①函数InitSPNode()用来建立一个稀疏矩阵的三元组表。
首先输入行数、列数和非零元的值,输入(-1,-1,-1)结束输入。
②函数showMatrix()用来输出稀疏矩阵。
算法中按矩阵a的列进行循环处理,对a的每一列扫描三元组,找出相应的元素,若找到,则交换其行号和列号,并存储到矩阵b的三元组中。
③函数TransposeSMatrix()用来完成稀疏矩阵的转置算法。
算法主要的工作是在p和col的两重循环中完成,时间复杂度为O(n*t)。如果非零元素个数t和m*n同数量级,则算法的时间复杂度变为O(m*n^2)。
3.概要设计:
函数 | 作用 |
nitSPNode() | 建立一个稀疏矩阵的三元组表 |
showMatrix() | 输出稀疏矩阵 |
TransposeSMatrix() | 完成稀疏矩阵的转置算法 |
4.程序设计流程图
5.源代码(vc++6.0 Dev-c++ 5.11调试通过):
#include<stdio.h>
#include<string.h>
#define OK 1
#define Maxsize 10 //用户自定义三元组最大长度
typedef struct //定义三元组表
{
int i,j;
int v;
}SPNode;
typedef struct //定义三元组表
{
SPNode data[Maxsize];
int m,n,t; //矩阵行,列及三元组表长度
}SPMatrix;
void InitSPNode(SPMatrix *a) //输入三元组表
{
int i,j,k,val,maxrow,maxcol;
maxrow=0;
maxcol=0;
i=j=0;
k=0;
while(i!=-1&&j!=-1) //两个其中一个等于-1结束输入
{
printf("输入(行 列 值):");
scanf("%d %d %d",&i,&j,&val);
a->data[k].i=i;
a->data[k].j=j;
a->data[k].v=val;
if(maxrow<i)maxrow=i;
if(maxcol<j)maxcol=j;
k++;
}
a->m=maxrow;a->n=maxcol;a->t=k-1;
}
void showMatrix(SPMatrix *a) //输出稀疏矩阵
{
int p,q;
int t=0;
for(p=0;p<=a->m;p++)
{for(q=0;q<=a->n;q++)
{ if(a->data[t].i==p&&a->data[t].j==q)
{ printf("%d ",a->data[t].v);
t++;
}
else printf("0 ");
}
printf("\n");
}
}
void TransposeSMatrix(SPMatrix *a,SPMatrix *b) //稀疏矩阵转置
{
int q,col,p;
b->m=a->n;b->n=a->m; b->t=a->t;
if(b->t)
{
q=0;
for(col=0;col<=a->n;++col) //按a的列序转置
for(p=0;p<a->t;++p) //扫描整个三元组表
if(a->data[p].j==col)
{
b->data[q].i=a->data[p].j;
b->data[q].j=a->data[p].i;
b->data[q].v=a->data[p].v;
++q;
}
}
}
void main(void)
{
SPMatrix a,b;
printf("\n 结束请输入(-1,-1,-1)\n");
InitSPNode(&a);
printf("输入矩阵为:\n");
showMatrix(&a); //转置前
TransposeSMatrix(&a,&b);
printf("输出矩阵为:\n");
showMatrix(&b); //转置后
}
6.运行结果:
这只是稀疏矩阵一个最简单的转置,另外还有加法,乘法等等。以及稀疏矩阵的十字链表存储等等。