openhelp100 发表于 2021-3-19 11:37:07

西交《数据结构》拓展资源(五)

西交《数据结构》拓展资源(五)
第五章 数组与广义表
  稀疏矩阵的基本运算
前记:这一章课件里主要讲了数组和广义表的属性和一些常用的操作。下面针对稀疏矩阵的基本操作做一个具体的实现,大家在运用中可以参考。
题目描述:实现一个能进行稀疏矩阵基本运算的运算器,包括相加、相减、相乘。
include<time.h>/*用于下面的srand((unsigned)time(NULL));函数的头文件*/
#include<stdio.h>
#include<stdlib.h>
#define MAX_ARRAY_DIM 2
#define MAXSIZE 100
typedef struct
{
int aa;
int dim;
int *base;
}array;
typedef struct
{
int i,j;/*记录非零元的行与列坐标*/
int e;/*记录非零原的数值*/
}triple;/*构成非零元素*/
typedef struct
{
triple data;/*预期非零原最大个数*/
int *rpos;/*记录各行第一个非零原的位置表*/
int mu,nu,tu;/*记录稀疏矩阵的行列和非零原个数*/
}tsmatrix;
main()
{
void initarray(array *a);/*数组初始化*/
void createsMatrix(array *a);/*创建稀疏矩阵*/
void inittsmatrix(array *a,tsmatrix *m);/*初始化稀疏矩阵三元组*/
void outputtsmatrix(tsmatrix *m);/*输出稀疏矩阵*/
void destroysmatrix(array *a);/*销毁稀疏矩阵*/
void outputarray(array *a);/*输出数组*/
void subtmatrix(tsmatrix *m,tsmatrix *n,tsmatrix *q);/*系数矩阵相减*/
void addsmatrix(tsmatrix *m,tsmatrix *n,tsmatrix *q);/*系数矩阵相加*/
void multsmatrix(tsmatrix *m,tsmatrix *n,tsmatrix *q);/*稀疏矩阵相乘*/
array a;
tsmatrix m,n,q;
int flag1=1,i;
srand((unsigned)time(NULL));
initarray(&a);/*初始化数组*/
createsMatrix(&a);/*创建稀疏矩阵*/
inittsmatrix(&a,&m);/*初始化稀疏矩阵三元组*/
outputtsmatrix(&m);/*输出稀疏矩阵*/
outputarray(&a);/*输出数组*/
destroysmatrix(&a);/*销毁原数组*/
initarray(&a);/*初始化数组*/
createsMatrix(&a);/*创建稀疏矩阵*/
inittsmatrix(&a,&n);/*初始化稀疏矩阵三元组*/
outputtsmatrix(&n);/*输出稀疏矩阵*/
outputarray(&a);/*输出数组*/
destroysmatrix(&a);/*销毁原数组*/
printf("2个三元数组已经创建成功,您要进行什么操作?\n1.(m+n)\n2.(m-n)\n3.(m*n)\n4.(n-m)\n");
while(flag1)
{
   fflush(stdin);
   scanf("%d",&i);
   switch(i)
   {
   case 1:addsmatrix(&m,&n,&q);flag1=0;break;
   case 2:subtmatrix(&m,&n,&q);flag1=0;break;
   case 3:multsmatrix(&m,&n,&q);flag1=0;break;
   case 4:subtmatrix(&n,&m,&q);flag1=0;break;
   default:printf("输入错误请重新输入\n您要进行什么操作?1.(m+n)\n2.(m-n)\n3.(m*n)\n4.(n-m)\n\n");
   }
}
printf("运算结果为\n");
outputtsmatrix(&q);/*输出运算结果*/
}
void initarray(array *a)/*创建数组*/
{
int i,j;
printf("请输入要创建的维数,(由于这里的作用是创建稀疏矩阵,建议输入2)\n");
scanf("%d",&a->dim);
if(a->dim!=MAX_ARRAY_DIM)
{
   printf("输入维数超过界限\n");
   exit(1);
}
for(i=0;i<a->dim;i++)
{
   printf("请输入第%d维的数据",i+1);
   scanf("%d",&a->aa);
   if(a->aa<1)
   {
    printf("输入超过范围\n");
    exit(1);
   }
}
j=1;
for(i=0;i<a->dim;i++)
   j*=a->aa;
if(!(a->base=(int *)malloc(j*sizeof(int))))
{
   printf("开辟空间失败\n");
   exit(1);
}
printf("数组创建成功\n");
}
void createsMatrix(array *a)/*创建稀疏矩阵*/
{
int i,j,k,l,m,n,flag1;
printf("是手动输入还是电脑自行创建?\n选1.电脑自行创建\n选0.手动创建\n");
scanf("%d",&i);
if(i!=1&&i!=0)
{
   printf("输入格式错误\n");
   exit(1);
}
if(i==0)/*手动输入*/
{
   printf("请输入\n");
   for(j=0;j<a->aa;j++)
   {
    for(k=0;k<a->aa;k++)
   scanf("%d",&a->base+k]);
    printf("\n");
   }
}
else/*电脑自动输入*/
{
   l=rand()%(a->aa*a->aa/4)+1;/*预期计算要输入多少个非零元*/
   for(j=0;j<a->aa;j++)/*先将程序中所有的元素赋予0*/
    for(k=0;k<a->aa;k++)
   a->base+k]=0;
    m=0;
    while(m<l)/*输入l个非零元*/
    {
   flag1=1;
   while(flag1)/*被赋予的元素原本必须是零*/
   {
      i=rand()%a->aa;/*自动选择行*/
      j=rand()%a->aa;/*自动选择列*/
      if(a->base+j]==0)/*所选择的元素是0*/
       flag1=0;/*推出循环,否则继续循环直到,是零为止*/
   }
   flag1=1;
   a->base+j]=rand()%10;/*赋值10以内*/
   n=rand()%10;
   if(n<5)
      a->base+j]*=-1;/*输入正负*/
   m++;
    }
}
}
void inittsmatrix(array *a,tsmatrix *m)/*稀疏矩阵非零原初始化*/
{
int i,j,k=0,*num;
for(i=0;i<a->aa;i++)/*输入非零原坐标及数据*/
   for(j=0;j<a->aa;j++)
    if(a->base+j]!=0)
    {
   m->data.i=i+1;
   m->data.j=j+1;
   m->data.e=a->base+j];
   k++;
    }
    m->mu=a->aa;/*记录行*/
    m->nu=a->aa;/*记录列*/
    m->tu=k;/*记录非零原数量*/
    if(!(num=(int *)malloc((m->mu+1)*sizeof(int))))/*num用于记录每行的非零原的个数*/
    {
   printf("空间开辟失败\n");
   exit(1);
    }
    if(!(m->rpos=(int *)malloc((m->mu+1)*sizeof(int))))/*本人认为数据结构上的rpos定义有错误,如果某一行全都是非零元那m->rpos=0并不是m->rpos+num所以以下的rpos操作可能与书上的原意不符*/
    {
   printf("空间开辟失败\n");
   exit(1);
    }
    for(i=0;i<=m->mu;i++)/*初始化num*/
   num=0;
    for(i=1;i<=m->tu;i++)/*记录每行非零原的个数*/
   ++num.i];
    if(num==0)/*如果第一行没有非零原的话那m->rops=0,这就是我修改的原因,如果按照书上写的话,那应该是1,对以后的操作有麻烦*/
    {
   m->rpos=0;
   j=0;
    }
    else/*否则记1*/
    {
   m->rpos=1;
   j=num;
    }
    for(i=2;i<=m->mu;i++)/*运算*/
    {
   if(num==0)
      m->rpos=0;/*当前这一行并没有非零元所以记录1*/
   else/*否则记录所对应的序列号*/
   {
      m->rpos=j+1;
      j+=num;
   }
   if(j>=m->tu)/*如果j的数量已经等于所有非零原的数量,那就应该退出循环*/
      break;
    }
    while(i<=m->mu)/*如果半路退出循环,那么剩下的每行,都没有非零原*/
   i++,m->rpos=0;
}
void outputtsmatrix(tsmatrix *m)/*输出稀疏矩阵*/
{
int i;
printf("三元组表为\n");
for(i=1;i<=m->tu;i++)
   printf("%d行 %d列 %d\n",m->data.i,m->data.j,m->data.e);
printf("行为%d列为%d\n",m->mu,m->nu);
for(i=1;i<=m->mu;i++)
   printf("%d行的第一个元素所在位置表的位置是%d\n",i,m->rpos);}
void destroysmatrix(array *a)/*销毁稀疏矩阵*/
{
if(!a->base)exit(1);
free(a->base);a->base=NULL;
printf("\n稀疏矩阵数组销毁成功(*^__^*) \n\n");
}
void outputarray(array *a)/*输出数组*/
{
int i,j;
for(i=0;i<a->aa;i++)
{
   for(j=0;j<a->aa;j++)
    printf("%2d ",a->base+j]);
   printf("\n");
}
}
void copysmatrix(tsmatrix *m,tsmatrix *t)/*复制稀疏矩阵*/
{
int i;
t->mu=m->mu,t->nu=m->nu,t->tu=m->tu;
if(!(t->rpos=(int *)malloc((t->mu+1)*sizeof(int))))
{
   printf("开辟控件失败\n");
   exit(1);
}
if(t->tu)
{
   for(i=1;i<=m->tu;i++)
   {
    t->data.i=m->data.i;
    t->data.j=m->data.j;
    t->data.e=m->data.e;
   }
}
for(i=1;i<=t->mu;i++)
   t->rpos=m->rpos;
}
void subtmatrix(tsmatrix *m,tsmatrix *n,tsmatrix *q)/*稀疏矩阵相减*/
{
int i,j,k,a,b,c,x,y,z,*num;
q->mu=m->mu>n->mu?m->mu:n->mu;
q->nu=m->nu>n->nu?m->nu:n->nu;
q->tu=0;
if(!(num=(int *)malloc((q->mu+1)*sizeof(int))))
{
   printf("创建空间失败\n");
   exit(1);
}
if(!(q->rpos=(int *)malloc((q->mu+1)*sizeof(int))))
{
   printf("创建空间失败\n");
   exit(1);
}
for(i=1;i<=q->mu;i++)
   num=0;
if(m->tu==0)
   copysmatrix(n,q);
else if(n->tu==0)
   copysmatrix(m,q);
else
{        i=j=k=1;
while(i<=m->tu&&j<=n->tu)
{
a=m->data.i;
b=m->data.j;
c=m->data.e;/*分别记录m的3元组的数据*/
x=n->data.i;
y=n->data.j;
z=n->data.e;
if(a==x)/*如果m,n行相等*/
{        if(b==y)/*如果行列都相等*/
{        if(c-z!=0)/*如果m-n!=0*/
{        num++;
q->data.i=a;
q->data.j=b;
q->data.e=c-z;
k++;
}
i++,j++;/*无论是否m-n==0i,j都要+1*/
}
else if(b<y)/*如果行相等但是列不相等q下一个三元组应该取坐标相对较小的*/
{        num++;
q->data.i=a;
q->data.j=b;
q->data.e=c;
k++;
i++;
}
else if(b>y)
{        num++;
q->data.i=x;
q->data.j=y;
q->data.e=-z;
k++;j++;
}
else
printf("不可能出现的事情\n");
}
else if(a>x)
{        num++;
q->data.i=x;
q->data.j=y;
q->data.e=-z;
k++;j++;
}
else if(a<x)
    {
   num++;
   q->data.i=a;
   q->data.j=b;
   q->data.e=c;
   k++;i++;
    }
    else
   printf("不可能发生的事情\n");
   }
   if(i>m->tu&&j<=n->tu)/*如果m的三元组记录完了但是n的三元组没有记录完那么剩下的应该全复制*/
   {
    while(j<=n->tu)
    {
   num.i]++;
   q->data.i=n->data.i;
   q->data.j=n->data.j;
   q->data.e=-n->data.e;
    }
   }
   else if(j>n->tu&&i<=m->tu)/*如果n的三元组记录完了但是m的三元组没有记录完那么剩下的应该全复制*/
   {
    while(i<=m->tu)
    {
   n->data.i].i;
   q->data.i=m->data.i;
   q->data.j=m->data.j;
   q->data.e=m->data.e;
    }
   }
   q->tu=k-1;
   if(num==0)/*如果第一行没有非零原的话那m->rops=0,这就是我修改的原因,如果按照书上写的话,那应该是1,对以后的操作有麻烦*/
   {
    q->rpos=0;
    j=0;
   }
   else/*否则记1*/
   {
    q->rpos=1;
    j=num;
   }
   for(i=2;i<=q->mu;i++)/*运算*/
   {
    if(num==0)
   q->rpos=0;/*当前这一行并没有非零元所以记录1*/
    else/*否则记录所对应的序列号*/
    {
   q->rpos=j+1;
   j+=num;
    }
    if(j>=q->tu)/*如果j的数量已经等于所有非零原的数量,那就应该退出循环*/
   break;
   }
   while(i<=q->mu)/*如果半路退出循环,那么剩下的每行,都没有非零原*/
   {
    i++;
    q->rpos=0;
   }
}
}
void addsmatrix(tsmatrix *m,tsmatrix *n,tsmatrix *q)/*稀疏矩阵相加*/
{
int i,j,k,a,b,c,x,y,z,*num;
q->mu=m->mu>n->mu?m->mu:n->mu;
q->nu=m->nu>n->nu?m->nu:n->nu;
q->tu=0;
if(!(num=(int *)malloc((q->mu+1)*sizeof(int))))
{
   printf("创建空间失败\n");
   exit(1);
}
if(!(q->rpos=(int *)malloc((q->mu+1)*sizeof(int))))
{
   printf("创建空间失败\n");
   exit(1);
}
for(i=1;i<=q->mu;i++)
   num=0;
if(m->tu==0)
   copysmatrix(n,q);
else if(n->tu==0)
   copysmatrix(m,q);
else
{
   i=j=k=1;
   while(i<=m->tu&&j<=n->tu)
   {
    a=m->data.i;
    b=m->data.j;
    c=m->data.e;/*分别记录m的3元组的数据*/
    x=n->data.i;
    y=n->data.j;
    z=n->data.e;
    if(a==x)/*如果m,n行相等*/
    {
   if(b==y)/*如果行列都相等*/
   {
      if(c+z!=0)/*如果m+n!=0*/
      {
       num++;
       q->data.i=a;
       q->data.j=b;
       q->data.e=c+z;
       k++;
      }
      i++,j++;/*无论是否m+n==0i,j都要+1*/
   }
   else if(b<y)/*如果行相等但是列不相等q下一个三元组应该取坐标相对较小的*/
   {
      num++;
      q->data.i=a;
      q->data.j=b;
      q->data.e=c;
      k++;
      i++;
   }
   else if(b>y)
   {
      num++;
      q->data.i=x;
      q->data.j=y;
      q->data.e=z;
      k++;j++;
   }
   else
      printf("不可能出现的事情\n");
    }
    else if(a>x)
    {
   num++;
   q->data.i=x;
   q->data.j=y;
   q->data.e=z;
   k++;j++;
    }
    else if(a<x)
    {
   num++;
   q->data.i=a;
   q->data.j=b;
   q->data.e=c;
   k++;i++;
    }
    else
   printf("不可能发生的事情\n");
   }
   if(i>m->tu&&j<=n->tu)/*如果m的三元组记录完了但是n的三元组没有记录完那么剩下的应该全复制*/
   {
    while(j<=n->tu)
    {
   num.i]++;
   q->data.i=n->data.i;
   q->data.j=n->data.j;
   q->data.e=n->data.e;
    }
   }
   else if(j>n->tu&&i<=m->tu)/*如果n的三元组记录完了但是m的三元组没有记录完那么剩下的应该全复制*/
   {
    while(i<=m->tu)
    {
   n->data.i].i;
   q->data.i=m->data.i;
   q->data.j=m->data.j;
   q->data.e=m->data.e;
    }
   }
   q->tu=k-1;
   if(num==0)/*如果第一行没有非零原的话那m->rops=0,这就是我修改的原因,如果按照书上写的话,那应该是1,对以后的操作有麻烦*/
   {
    q->rpos=0;
    j=0;
   }
   else/*否则记1*/
   {
    q->rpos=1;
    j=num;
   }
   for(i=2;i<=q->mu;i++)/*运算*/
   {
    if(num==0)
   q->rpos=0;/*当前这一行并没有非零元所以记录1*/
    else/*否则记录所对应的序列号*/
    {
   q->rpos=j+1;
   j+=num;
    }
    if(j>=q->tu)/*如果j的数量已经等于所有非零原的数量,那就应该退出循环*/
   break;
   }
   while(i<=q->mu)/*如果半路退出循环,那么剩下的每行,都没有非零原*/
   {
    i++;
    q->rpos=0;
   }
}
}
void multsmatrix(tsmatrix *m,tsmatrix *n,tsmatrix *q)/*稀疏矩阵相乘*/
{
int i,j,k,l,o,p,x,y,*a,*num;
if(!(a=(int *)malloc(((m->mu+1)*(n->nu+1))*sizeof(int))))/*创建一个跟q相同大小的空间用来记录此坐标是否已经输入一个数*/
{
   printf("开辟空间失败\n");
   exit(1);
}
if(m->nu!=n->mu)
{
   printf("不匹配\n");
   exit(1);
}
q->mu=m->mu,q->nu=n->nu,q->tu=0;/*初始化*/
if(!(num=(int *)malloc((m->mu+1)*sizeof(int))))
{
   printf("开辟空间失败\n");
   exit(1);
}
if(!(q->rpos=(int *)malloc((q->mu+1)*sizeof(int))))
{
   printf("空间开辟失败");
   exit(1);
}
for(i=1;i<=q->mu;i++)
   num=0;
if(m->tu*n->tu!=0)
{
   for(i=1;i<=m->mu;i++)/*初始化a数组*/
    for(j=1;j<=n->nu;j++)
   a=0;
    for(i=1;i<=m->tu;i++)
    {
   o=m->data.i;
   p=m->data.j;
   if(n->rpos==0)
      continue;
   l=p+1;
   while(n->rpos==0&&l<=n->mu)
      l++;
   if(l>n->mu)
      j=n->tu+1;
   else
      j=n->rpos;
   for(k=n->rpos;k<j;k++)/*k-j的范围是本行非零远的个数*/
   {
      x=n->data.i;/*x,y分别是n->data的行和列*/
      y=n->data.j;
      if(a!=0)
       q->data].e+=m->data.e*n->data.e;/*如果此空间已经输入一个数了,那么在相应的位置累加*/
      else
      {
       q->data[++q->tu].e=m->data.e*n->data.e;
       q->data.i=o;
       q->data.j=y;
       a=q->tu;/*此位置记录q->tu*/
       num++;
      }
   }
    }
    for(i=1;i<=q->mu;i++)
   printf("%d ",num);
    if(num==0)/*如果第一行没有非零原的话那m->rops=0,这就是我修改的原因,如果按照书上写的话,那应该是1,对以后的操作有麻烦*/
    {
   q->rpos=0;
   j=0;
    }
    else/*否则记1*/
    {
   q->rpos=1;
   j=num;
    }
    for(i=2;i<=q->mu;i++)/*运算*/
    {
   if(num==0)
      q->rpos=0;/*当前这一行并没有非零元所以记录1*/
   else/*否则记录所对应的序列号*/
   {
      q->rpos=j+1;
      j+=num;
   }
   if(j>=q->tu)/*如果j的数量已经等于所有非零原的数量,那就应该退出循环*/
      break;
    }
    while(i<=q->mu)/*如果半路退出循环,那么剩下的每行,都没有非零原*/
   i++,q->rpos=0;
}
}
本内容由易百网整理发布
网址 www.openhelp100.com
QQ 515224986
页: [1]
查看完整版本: 西交《数据结构》拓展资源(五)