稀疏矩阵

稀疏矩阵的定义:设m*n矩阵中有t个非0元素,且t<<m*n,这样的矩阵就是稀疏矩阵

稀疏矩阵的储存:用三元组表储存(将三元组按行优先,同一行中列号由小到大的规律排列成一个线性表)

首先定义一个结构体来储存三元组表的元素

typedef struct
{
    int i;        //行坐标
    int j;        //列坐标
    int value;    //该点的值
} item;

然后定义三元组表

Typedef struct
{
Int h,l,sum//稀疏矩阵的行数、列数以及非零元素的个数
Item data[100];
}T;

稀疏矩阵的转置:

T* trans(T *A){//传入数组A的地址,然后返回一个转置后的数组B的地址
T *B;//定义数组B的地址
B=(T*)malloc(sizeof(T));//为数组B分配空间
B->h=A->l;B->l=A->h;B->sum=A->sum;
//B数组的行数等于A数组的列数;B数组的列数等于A数组的行数
If(B->sum>0){//数组中有非0元素
Num=1;//三元组表的下标;
for(int c=1;c<=A->l;c++){//根据三元组表的格式,得按照A的列序进行转置
for(int p=1;p<=A->sum;p++){//扫描整个三元组表
If(A->data[p].j==c){
//三元组表中第p个数值所在数组的位置的列数等于A的列数时,进入置换
 B->data[num].i=A->data[p].j;
B->data[num].j=A->data[p]i;
B->data[num]. value=A->data[p]. value;
Num++;
}
}
}
}
Return B;
}

置换代码思想:就是按照数组A的列数进行置换,一列一列来,保证三元表的顺序。然后内层循环查找整个三元表,看看三元表中有没有列数符合当前外层循环设置的列数的,如果符合进入置换。

缺点:需要反复搜索A表,耗费时间多

改进的置换代码:(若能直接确定A中每一个三元组在B中的位置,则对A表扫描一次即可)

我们可以知道第一列的第一个非零元素一定存储在B.data[1],如果还知道第一列的非零元素个数的话,就可以确定第二列的第一个非零元素的位置=(第一列的非零元素的位置+第一列的非零元素个数的话),第三列的第一个非零元素的位置=(第二列的非零元素的位置+第二列的非零元素个数的话),以此类推,就可以确定转置后的整个三元组表。

T* trans(T *A){//传入数组A的地址,然后返回一个转置后的数组B的地址
T *B;//定义数组B的地址
B=(T*)malloc(sizeof(T));//为数组B分配空间
B->h=A->l;B->l=A->h;B->sum=A->sum;
//B数组的行数等于A数组的列数;B数组的列数等于A数组的行数
Int col,t,p,q,x;
Int num[20];//记录A数组中每一列的非零元素个数
Int cpot[20];//记录A数组中每一列第一个非0元素的位置
If(B->sum>0){//数组中有非0元素
memset(num,0,sizeof(num));//初始化num数组,将数组中所有的值都初始化为0
For(t=1;t<=A->sum;t++){//求A中每一列所含非零元素的个数
num[A->data[t].j]++;
}
Cpot[1]=1;
For(col=2;col<=A->l;col++){//求矩阵A中每一列第一个非0元素所在的位置
Cpot[col]=cpot[col-1]+num[col-1];}
For(p=1;p<=A->sum;p++){
x=A->data[p].j;//x赋值为三元组表中第p行的元素的列数
q=cpot[x];//q等于数组A在该列中的第一个元素所在的位置
B->data[q].i=A->data[p].j
B->data[q].j=A->data[p].i
B->data[q].value=A->data[p].value
Copt[x]++;//下标记录加一
//小标记录加一之后,当下次再遇到相同列数的元素时,就可以直接添加在后面而不是添加到之前的位置把之前的值覆盖掉。
}
}
Return B;
}

稀疏矩阵的乘法:

例如现在有两个矩阵:A和B,假设A有i行,B有j列,则矩阵C的大小为:i*j;

传统矩阵的乘法思想:用A的列去乘B的行,求和之后在放到C矩阵当中去存储。一步到位求出C矩阵某个位置的数值。

稀疏矩阵的乘法思想:用A矩阵当中的一个数去乘B矩阵当中的一行数值,然后在存到temp[]累加数组当中去。意思就是求C11与求C12是同时进行。

SPMatrix *MulSMatrix(SPMatrix *A,SPMatrix *B){
SPMatrix *C;
Int p,q,i,j,k,r;
Int temp[100];//累加器
Int num[B->hang];//记录B数组每一行非零元素的个数
Int ropt[B->hang];//记录B矩阵中每一行第一个非零元素的位置

If(A->lie!=B->hang)return NULL;//A、B矩阵无法进行乘法运算
C=(SPMatrix *)malloc(sizeof(SPMatrix));
C->hang=A->hang;
C->lie=B->lie;
If(A->sum*B->sum==0)//当A或B矩阵当中的非零元素为0个时
{
C->sum=0;
Retrun C;
}

//初始化num数组
For(i=1;i<=B->hang;i++) num[i]=0;
//求num[]数组的数值
For(k=1;k<B->sum;k++){
i=B->data[k].i;
Num[i]++;
}

Ropt[1]=1;
//求ropt[]数组的数值
For(i=2;i<=B->hang;i++){
Ropt[i]=ropt[i-1]+num[i-1];
}

r=0;//计算C中非零元素的个数
p=1;//指示A.data中当前非零元素的位置

For(i=1;i<=A->hang;i++){//A数组的第i行
For(j=1;j<=B->lie;j++) temp[j]=0;//初始化temp[]数组

//当A数组中的第p个元素指向的列等于i时,进入循环
While(A->data[p].i==i){
K=A->data[p].j;

//求B数组中第K行的最后一个元素的位置
If(k<B->mu) t=ropt[k+1]-1;
Else t=B->sum;

For(q=ropt[k];q<=t;q++){
//第k行的第一个位置循环到第k行的最后一个位置
J=B->data[q].j;
Temp[j]=temp[j]+A->data[p].v*B->data[q].v;
}
P++;

//将累加器中已经累加完的数值存入C中
For(j=1;j<=B->lie;j++){
If(temp[j]){
R++;
C->data[r]={i,j,temp[j]};
}
}
}
}
C->sum=r;
Return C;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值