数据结构与算法分析课程设计:稀疏矩阵的应用
1.设计题目与功能需求分析
1.1设计题目
《稀疏矩阵应用》
要求:实现三元组,十字链表下的稀疏矩阵的加、转、乘的实现。
1.2功能需求分析
(1)设计函数建立稀疏矩阵,初始化值。
(2)设计函数输出稀疏矩阵的值。
(3)构造函数进行两个稀疏矩阵相加,输出最终的稀疏矩阵。
(4)构造函数进行两个稀疏矩阵的相乘,输出最终的稀疏矩阵。
(5)构造函数进行稀疏矩阵的转置,并输出结果。
(6)退出系统。
2.概要设计
2.1功能模块设计
从系统的功能需求分析,得到系统主要包括以下几大功能模块,分别是建立主函数、创建三元组表、创建矩阵、矩阵相加减、矩阵转置等。其功能模块图如下图所示:

图1 系统功能模块图
2.2模块简介
依据程序的功能模块划分,各模块定义如下:
(1)定义稀疏矩阵框架
模块名:struct OLNode
模块描述:通过此模块可以定义矩阵内部元素类型及指针类型。
(2)创建稀疏矩阵信息
模块名:void Create(CrossList &M)
模块描述:根据文字提示,输入稀疏矩阵的行、列、非零元的全部信息。
(3)输出符合上述步骤中信息的稀疏矩阵
模块名:void Print(CrossList M)
模块描述:以矩阵的显示方式显示稀疏矩阵。
(4)进行稀疏矩阵的加运算
模块名:void Add(CrossList M,CrossList N,CrossList &Q)
模块描述:根据文字提示,如果两个矩阵不是同类型的,程序返回给操作系统的返回码是OVERFLOW;如果两个矩阵是同类型的,相加程序运行。
(5)进行稀疏矩阵的转置运算
模块名:void Trans(CrossList M,CrossList &N)
模块描述:定义结点,扫描矩阵,进行矩阵的转置运算。
(6)进行稀疏矩阵的乘运算
模块名:void Mult(CrossList M,CrossList N,CrossList &Q)
模块描述:判断矩阵M的总列数是否等于矩阵N的总行数,若是,程序运行,否则,提示出错。
3.详细设计
3.1数据结构
本程序采用结构体数组,对稀疏矩阵中非零元素的行、列、值以及指针。
1 struct OLNode 2 { 3 int i,j; 4 ElemType e; 5 OLNode *right,*down; 6 }; 7 typedef OLNode *OLink; 8 struct CrossList 9 { 10 OLink *rhead,*chead; 11 int mu,nu,tu; 12 };
3.2主函数的算法设计
首先显示菜单及运用菜单选择实现相应功能,输入稀疏矩阵行、列以及非零元,系统菜单调用采用while循环,在循环体中用switch语句调用各个功能函数,最后退出程序。
主函数的程序流程图如下图所示:

图2 函数流程图
3.3程序代码实现
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<iostream.h> 4 #include<process.h> 5 #define OK 1 6 #define ERROR 0 7 #define OVERFLOW -2 8 typedef int ElemType; 9 10 //------------------------------------------------------------------------------------------------ 11 12 struct OLNode 13 { 14 int i,j; //非零元所在行、列 15 ElemType e; //非零元值 16 OLNode *right,*down; //定义向右域和向下域 17 }; 18 19 typedef OLNode *OLink; 20 21 struct CrossList 22 { 23 OLink *rhead,*chead; //行、列表头的头节点 24 int mu,nu,tu; //矩阵的行、列和非零元个数 25 }; 26 27 28 //------------------------------------------------------------------------------------------------ 29 30 31 void Create(CrossList &M) //矩阵的创建 32 { 33 int i,j,k,m,n,t; 34 ElemType e; //用于存放非零元值 35 OLNode *p,*q; 36 printf("Please input the rows 、columns and the values of the matrix:"); 37 scanf("%d%d%d",&m,&n,&t); //输入稀疏矩阵的行、列、非零元个数 38 M.mu=m; //把矩阵的总行数存入M.mu 39 M.nu=n; //把矩阵的总列数存入M.nu 40 M.tu=t; //把矩阵的非零元个数存入M.tu 41 M.rhead=(OLink*)malloc((m+1)*sizeof(OLink)); //给对象M的行分配m+1个结点大小的空间用行头指针M.rhead指向第一个行结点 42 if(!M.rhead) //假如头结点分配成功 43 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 44 M.chead=(OLink*)malloc((n+1)*sizeof(OLink)); //给对象M的列分配n+1个结点大小的空间用列头指针M.chead指向第一个列结点 45 if(!M.chead) //假如头结点分配成功 46 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 47 for(k=1;k<=m;k++) //初始化行头指针 48 M.rhead[k]=NULL; 49 for(k=1;k<=n;k++) //初始化列头指针 50 M.chead[k]=NULL; 51 printf("Please input %d data:\n",M.tu); 52 for(k=0;k<t;k++) 53 { 54 scanf("%d%d%d",&i,&j,&e); //输入t个非零元的信息 55 if(i>m||j>n) //假如输入的元素不在矩阵中 56 { 57 printf("Please input again:\n"); 58 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 59 } 60 else //假如输入的元素在矩阵中 61 { 62 p=(OLNode*)malloc(sizeof(OLNode)); //为p分配一个结点大小的空间 63 if(!p) //假如p不存在 64 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 65 p->i=i; //把非零元的行值赋给p->i 66 p->j=j; //把非零元的列值赋给p->j 67 p->e=e; //把非零元的值赋给p->e 68 if(M.rhead[i]==NULL||M.rhead[i]->j>j) //如果第i行的第一个结点为空或者要插入的非零元的列值小于第i行的第一个结点的列值 69 { 70 //p插入该行第一节点处 71 p->right=M.rhead[i]; //p的向右域指向没有插入前的第i行的第一个结点 72 M.rhead[i]=p; //p指向没有插入前的第i行的第一个结点 73 } 74 else 75 { 76 //否则寻找行表插入位置 77 for(q=M.rhead[i];q->right&&q->right->j<j;q=q->right);//这里的;表示对这个循环不执行任何操作 78 p->right=q->right; //p的右向域指向q的右向域 79 q->right=p; //p指向q的右向域 80 } //完成行插入 81 if(M.chead[j]==NULL||M.chead[j]->i>i) //假如第一个列结点为空或者第j列的第一个结点的行值大于要插入的行值 82 { 83 //p插入该列第一节点处 84 p->down=M.chead[j]; //p的向下域指向没有插入前的第j列的第一个结点 85 M.chead[j]=p; //p指向没有插入前的第j列的第一个结点 86 } //完成列插入 87 else 88 { 89 //否则寻找列表插入位置 90 for(q=M.chead[j];q->down&&q->down->i<i;q=q->down);//这里的;表示对这个循环不执行任何操作 91 p->down=q->down; //p的向下域指向q的向下域 92 q->down=p; //p指向q的向下域 93 } //完成列插入 94 } 95 } 96 } 97 98 99 //------------------------------------------------------------------------------------------------ 100 101 void Print(CrossList M) //矩阵的输出 102 { 103 int i,j,k; 104 OLink p; //定义结点指针p 105 int array[100][100]; //定义二元数组array[100][100] 106 for(i=1;i<=M.mu;i++) //行循环 107 { 108 for(j=1;j<=M.nu;j++) //列循环 109 { 110 array[i][j]=0; //初始化数组所需部分 111 } 112 } 113 for(k=1;k<=M.nu;k++) //将所有非零元的值存入对应的数组中 114 { 115 p=M.rhead[k]; //p指向第k行的第一个结点 116 while(p) 117 { 118 //将第k行的非零元存入数组中 119 array[p->i][p->j]=p->e; //将这个结点的非零元存入数组中 120 p=p->right; //p指向下一个向右域 121 } 122 } 123 for(i=1;i<=M.mu;i++) //行循环 124 { 125 for(j=1;j<=M.nu;j++) //列循环 126 { 127 if(j==M.nu) 128 cout<<array[i][j]<<endl; //如果是行的最后一个结点则换行 129 else 130 cout<<array[i][j]<<" "; //以矩阵的显示方式显示稀疏矩阵 131 } 132 } 133 } 134 135 136 //------------------------------------------------------------------------------------------------ 137 138 139 void Add(CrossList M,CrossList N,CrossList &Q) //矩阵M和矩阵N相加并存入矩阵Q 140 { 141 int i,k; 142 OLink p,pq,pm,pn; 143 OLink *col; 144 if(M.mu!=N.mu||M.nu!=N.nu) //如果两个矩阵不是同类型的 145 { 146 printf("The two matrixes is not of the same type!/n"); 147 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 148 } 149 //对Q进行初始化 150 Q.mu=M.mu; //矩阵Q的总行数和矩阵M的总数相同 151 Q.nu=M.nu; //矩阵Q的总列数和矩阵M的总数相同 152 Q.tu=0; //将矩阵Q的非零元个数初始化为零 153 Q.rhead=(OLink*)malloc((Q.mu+1)*sizeof(OLink)); //给对象Q的行分配Q.mu+1个结点大小的空间用行头指针Q.rhead指向第一个行结点 154 if(!Q.rhead) //如果行分配空间成功 155 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 156 Q.chead=(OLink*)malloc((Q.nu+1)*sizeof(OLink)); //给对象Q的列分配Q.nu+1个结点大小的空间用列头指针Q.chead指向第一个列结点 157 if(!Q.chead) //如果列分配空间成功 158 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 159 for(k=1;k<=Q.mu;k++) //初始化行 160 Q.rhead[k]=NULL; 161 for(k=1;k<=Q.nu;k++) //初始化列 162 Q.chead[k]=NULL; 163 col=(OLink*)malloc((Q.nu+1)*sizeof(OLink));//生成指向列的起始节点的指针 164 if(!col) //如果分配空间成功 165 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 166 for(k=1;k<=Q.nu;k++) //赋初始值 167 col[k]=NULL; 168 for(i=1;i<=M.mu;i++) //按行序相加 169 { 170 pm=M.rhead[i]; //pm指向矩阵M的第i行的头结点 171 pn=N.rhead[i]; //pn指向矩阵N的第i行的头结点 172 while(pm&&pn) //如果pm和pn都存在 173 { 174 if(pm->j<pn->j) //矩阵M当前结点的列小于矩阵N当前结点的列 175 { 176 //生成Q的结点 177 p=(OLink)malloc(sizeof(OLNode)); //给p分配一个结点大小的空间 178 if(!p) //如果分配空间不成功 179 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 180 Q.tu++; //矩阵Q的非零元个数加1 181 p->i=i; //把非零元的行赋给p->i 182 p->j=pm->j; //把矩阵M中当前结点列的值赋给p->j 183 p->e=pm->e; //把矩阵M中当前结点的元素值赋给p->e 184 p->right=NULL; //p的向右域为空 185 pm=pm->right; //pm右移 186 } 187 else if(pm->j>pn->j) //矩阵M当前结点的列大于矩阵N当前结点的列 188 { 189 p=(OLink)malloc(sizeof(OLNode));//给p分配一个结点大小的空间 190 if(!p) //如果分配空间不成功 191 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 192 Q.tu++; //矩阵Q的非零元个数加1 193 p->i=i; //把矩阵当前非零元的行赋给p->i 194 p->j=pn->j; //把矩阵N中当前结点列的值赋给p->j 195 p->e=pn->e; //把矩阵N中当前结点的元素值赋给p->e 196 p->right=NULL; //p的向右域为空 197 pn=pn->right; //pn右移 198 } 199 else if(pm->e+pn->e) //M,N当前结点的列相同并且两元素之和非零 200 { 201 p=(OLink)malloc(sizeof(OLNode));//给p分配一个结点大小的空间 202 if(!p) //如果分配空间不成功 203 exit(OVERFLOW); //退出程序,程序返回给操作系统的返回码是OVERFLOW 204 Q.tu++; //矩阵Q的非零元个数加1 205 p->i=i; //把矩阵当前非零元的行赋给p->i 206 p->j=pn->j; //把矩阵当前非零元的列赋给p->j 207 p->e=pm->e+pn->e; //把矩阵M当前非零元的值和矩阵N当前非零元的值相加赋给p->e 208 p->right=NULL; //p的向右域为空 209 pm=pm->right; //pm右移 210 pn=pn->right; //pn右移 211 } 212 else //两元素相加为零 213 { 214 pm=pm->right; //pm右移 215 pn=pn->right; //pn右移 216 continue; //不执行下面的程序,回到循环 217 } 218 if(Q.rhead[i]==NULL) //如果当前行的头结点为空 219 Q.rhead[i]=pq=p; //把p结点中的数据赋给pq结点和结点Q.rhead[i],pq结点用来保存当前的位置 220 else //如果当前的头结点不为空 221 { 222 pq->right=p; //pq的向右域指向p 223 pq=pq->right; //pq指向pq的向右域 224 } //完成行插入 225 if(Q.chead[p->j]==NULL) //如果当前列的头结点为空 226 Q.chead[p->j]=col[p->j]=p; //把p结点中的数据赋给结点col[p->j]和当前列的头结点Q.chead[p->j] 227 else 228 { 229 //如果当前结点不为空,则插入p结点 230 col[p->j]->down=p; 231 col[p->j]=col[p->j]->down; 232 } 233 } 234 while(pm) //如果矩阵M中的结点还没有插完,将矩阵M该行的剩余元素插入矩阵Q 235 { 236 p=(OLink)malloc(sizeof(OLNode)); //给结点p分配空间 237 if(!p) 238 exit(OVERFLOW); 239 Q.tu++; //矩阵非零元个数加1 240 p->i=i; //把当前结点的行、列、和值插入p中 241 p->j=pm->j; 242 p->e=pm->e; 243 p->right=NULL; //p的向右域为空 244 pm=pm->right; //pm右移 245 if(Q.rhead[i]==NULL) //如果当前行头结点为空,直接插入p结点 246 Q.rhead[i]=pq=p; 247 else //如果当前行头结点不为空,插入p结点 248 { 249 pq->right=p; 250 pq=pq->right; 251 } 252 if(Q.chead[p->j]==NULL) //如果当前列头结点为空,直接插入p结点 253 Q.chead[p->j]=col[p->j]=p; 254 else //如果当前列头结点不为空,插入p结点 255 { 256 col[p->j]->down=p; 257 col[p->j]=col[p->j]->down; 258 } 259 } 260 while(pn) //如果矩阵N中的结点还没有插完,将矩阵N该行的剩余元素插入矩阵Q 261 { 262 p=(OLink)malloc(sizeof(OLNode)); //给结点p分配空间 263 if(!p) 264 exit(OVERFLOW); 265 Q.tu++; //矩阵非零元个数加1 266 p->i=i; //把当前结点的行、列、和值插入p中 267 p->j=pn->j; 268 p->e=pn->e; 269 p->right=NULL; //p的向右域为空 270 pn=pn->right; //pn右移 271 if(Q.rhead[i]==NULL) //如果当前行头结点为空,直接插入p结点 272 Q.rhead[i]=pq=p; 273 else //如果当前行头结点不为空,插入p结点 274 { 275 pq->right=p; 276 pq=pq->right; 277 } 278 if(Q.chead[p->j]==NULL) //如果当前列头结点为空,直接插入p结点 279 Q.chead[p->j]=col[p->j]=p; 280 else //如果当前列头结点不为空,插入p结点 281 { 282 col[p->j]->down=p; 283 col[p->j]=col[p->j]->down; 284 } 285 } 286 } 287 for(k=1;k<=Q.nu;k++) //使得每一列的最后一个结点的向下域为空 288 if(col[k]) 289 col[k]->down=NULL; 290 free(col); //释放col的空间 291 } 292 293 //------------------------------------------------------------------------------------------------ 294 295 296 void Trans(CrossList M,CrossList &N) //将矩阵M转置到矩阵N中 297 { 298 OLink p,q,s; //定义三个结点p、q、s 299 int i,j; 300 N.mu=M.mu; //将矩阵M中的行、列和非零元值赋给矩阵N 301 N.nu=M.nu; 302 N.tu=M.tu; 303 if(N.rhead==NULL) //如果矩阵N的行为空 304 N.rhead=(OLink *)malloc((N.mu+1)*sizeof(OLink));//给矩阵N的行分配N.mu+1个结点大小的空间 305 for(i=1;i<=N.mu;i++) //对矩阵N的行进行初始化 306 N.rhead[i]=NULL; 307 if(N.chead==NULL) //如果矩阵N的列为空 308 N.chead=(OLink *)malloc((N.nu+1)*sizeof(OLink));//给矩阵N的列分配N.nu+1个结点大小的空间 309 for(j=1;j<=N.nu;j++) //对矩阵N的列进行初始化 310 N.chead[j]=NULL; 311 for(i=1;i<=M.mu;i++) 312 { 313 for(s=M.rhead[i];s!=NULL;s=s->right) //对矩阵M的第i行进行扫描 314 { 315 p=(OLink)malloc(sizeof(OLink)); //给p分配一个结点大小的空间 316 p->i=s->j; //将扫描到的结点中的数据进行转置后存到结点p中 317 p->j=s->i; 318 p->e=s->e; 319 if(N.rhead[p->i]==NULL || N.rhead[p->i]->j>p->j)//如果p结点所在行的头结点为空或者头结点的列大于p结点的列值将p结点插入到第一个结点 320 { 321 p->right=N.rhead[p->i]; 322 N.rhead[p->i]=p; 323 } 324 else 325 { 326 for(q=N.rhead[p->i];q->right && q->right->j<p->j;q=q->right);//扫描直到扫描到的列值大于要插入的结点的列值,则把p结点插入到这个结点的后面 327 p->right=q->right; 328 q->right=p; 329 } 330 if(N.chead[p->j]==NULL || N.chead[p->j]->i > p->i)//如果p结点所在列的头结点为空或者头结点的行值大于p结点的行值将p结点插入到第一个结点 331 { 332 p->down=N.chead[p->j]; 333 N.chead[p->j]=p; 334 } 335 else 336 { 337 for(q=N.chead[p->j];q->down && q->down->i < p->i; q=q->down);//扫描当前列,直到扫描到的结点的行值大于要插入的结点的行值,则把p结点插入到这个结点的后面 338 p->down=q->down; 339 q->down=p; 340 } 341 } 342 } 343 } 344 345 346 //------------------------------------------------------------------------------------------------ 347 348 349 350 void Mult(CrossList M,CrossList N,CrossList &Q)//把矩阵M和矩阵N相乘并存入到矩阵Q中 351 { 352 int i,j,e; 353 OLink q,p0,q0,q1,q2; 354 if(M.nu!=N.mu) //如果矩阵M的总列数不等于矩阵N的总行数,则不能矩阵相乘 355 { 356 printf("The matrix what you input is error!/n"); 357 exit(OVERFLOW); 358 } 359 else //如果矩阵M的总列数等于矩阵N的总行数 360 { 361 Q.mu=M.mu; //把矩阵M的总行数赋给Q.mu 362 Q.nu=N.nu; //把矩阵N的总列数赋给Q.nu 363 Q.tu=0; //矩阵Q的非零元个数置为零 364 Q.rhead=(OLink*)malloc((Q.mu+1)*sizeof(OLink)); //给矩阵Q的行头指针分配Q.mu+1个结点大小的空间 365 if(!Q.rhead) 366 exit(OVERFLOW); 367 Q.chead=(OLink*)malloc((Q.nu+1)*sizeof(OLink)); //给矩阵Q的列头指针分配Q.nu+1个结点大小的空间 368 if(!Q.chead) 369 exit(OVERFLOW); 370 for(i=1;i<=Q.mu;i++) //初始化行 371 Q.rhead[i]=NULL; 372 for(i=1;i<=Q.nu;i++) //初始化列 373 Q.chead[i]=NULL; 374 for(i=1;i<=Q.mu;i++) 375 for(j=1;j<=Q.nu;j++) 376 { 377 p0=M.rhead[i]; //p0指向矩阵M第i行头结点 378 q0=N.chead[j]; //q0指向矩阵N第j列头结点 379 e=0; //定义变量e的值为0 380 while(p0&&q0) //当矩阵M和矩阵N的当前结点都存在时 381 { 382 if(q0->i<p0->j) //如果q0当前所在行小于p0当前所在列,q0下移 383 q0=q0->down; 384 else if(q0->i>p0->j) //如果q0当前所在行大于p0当前所在列,p0右移 385 p0=p0->right; 386 else 387 { 388 e=e+p0->e*q0->e; //乘积累加 389 q0=q0->down; //行列后移 390 p0=p0->right; 391 } 392 } 393 if(e) //e不为零则插入Q 394 { 395 Q.tu++; //矩阵Q的非零元个数加1 396 q=(OLink)malloc(sizeof(OLNode)); //给q分配空间 397 if(!q) 398 exit(OVERFLOW); 399 q->i=i; //把当前元素的行、列和值赋给结点q 400 q->j=j; 401 q->e=e; 402 q->right=NULL; //结点q的向右域为空 403 q->down=NULL; //结点q的向下域为空 404 if(!Q.rhead[i]) //如果Q矩阵当前行的头结点为空,将结点q中的数据赋给Q.rhead和结点q1:用来存储当前位置 405 Q.rhead[i]=q1=q; 406 else //否则将q中的数据赋给q1的向右域,并将q1右移 407 q1=q1->right=q; 408 if(!Q.chead[j]) //如果Q矩阵当前列的头结点为空,将结点q中的数据赋给Q.chead 409 Q.chead[j]=q; 410 else 411 { 412 q2=Q.chead[j]; //将当前列的头结点数据赋给q2 413 while(q2->down) //如果q2的向下域存在 414 q2=q2->down; //q2下移 415 q2->down=q; //把当前要插入的结点q插入到结点q2的后面 416 } 417 } 418 } 419 } 420 } 421 422 //------------------------------------------------------------------------------------------------ 423 424 425 void main() 426 { 427 CrossList A,B,C; //声明三个矩阵 428 int Select; //用来表示所要选择的序号 429 cout<<"*****************************************************************************"<<endl; 430 cout<<"******************************"<<"请选择你需要的操作"<<"*****************************"<<endl; 431 printf("/t/t/t<1>.Press 1 to add the array;\n"); 432 printf("/t/t/t<2>.Press 2 to trans the array;\n"); 433 printf("/t/t/t<3>.Press 3 to multiply the array;\n"); 434 cout<<"*****************************************************************************"<<endl; 435 while(printf("Please input the serial number:"),cin>>Select) 436 { 437 switch(Select) 438 { 439 case 1 : //稀疏矩阵相加 440 { 441 Create(A); 442 Create(B); 443 cout<<"The array A is:"<<endl; 444 Print(A); 445 cout<<"To add array B:"<<endl; 446 Print(B); 447 Add(A,B,C); //把矩阵A和矩阵B相加存入到矩阵C中 448 cout<<"The result is:"<<endl; 449 Print(C); //输出矩阵C 450 break; 451 } 452 case 2 ://稀疏矩阵转置 453 { 454 Create(A); 455 Create(B); 456 cout<<"The array A is:"<<endl; 457 Print(A); 458 cout<<"Trans to B:"<<endl; 459 Trans(A,B); //将矩阵A转置到矩阵B中 460 cout<<"The result is:"<<endl; 461 Print(B); //输出矩阵B 462 break; 463 } 464 case 3 : //稀疏矩阵相乘 465 { 466 Create(A); 467 Create(B); 468 cout<<"The array A is:"<<endl; 469 Print(A); 470 cout<<"To multiply array B:"<<endl; 471 Print(B); 472 Mult(A,B,C); //把矩阵A和矩阵B相乘所得的矩阵存入矩阵C中 473 cout<<"The result is:"<<endl; 474 Print(C); //输出矩阵C 475 break; 476 } 477 } 478 } 479 }
4.运行结果与调试分析
4.1系统主界面

图3 系统主界面
4.2输入稀疏矩阵相关信息
输入要进行的操作,之后输入稀疏矩阵行、列、非零元素个数。根据提示再输入非零元素所在行、列以及值。

图4 构造稀疏矩阵
若在输入非零元素行、列时,所输入的位置并不在矩阵中则程序报错,需要重新进行输入。

图5 非零元素不在所输入的矩阵中时,程序报错提示
4.3输出稀疏矩阵加运算结果
输入稀疏矩阵,进行矩阵的加法运算

图6 输出稀疏矩阵的加运算运行结果
若输入的两个矩阵行、列数不同,在输出两个输入的矩阵后,程序报错并提示两个矩阵类型不同。

图7 进行加运算时,两个矩阵类型不同时程序报错提示
4.4输出稀疏矩阵转置运算结果

图8 输出稀疏矩阵的转置运算运行结果
4.5输出稀疏矩阵乘运算结果

图9 输出稀疏矩阵的乘运算运行结果
5.总结体会
通过此次课程设计,我以实际程序的运行,熟悉了用三元组、十字链表下稀疏矩阵的加、转、乘运算。在实验中,我们要培养的是自己的独立思考能力和独立解决问题的能力。通过此次试验我也认识到了数据结构与算法分析这门课程的重要性,以及C语言功能的强大。C语言可以让计算机进行各种需要的操作,当然进行这些操作的前提是自己的技术水平要过关。
纸上得来终觉浅,得知此事要躬行。数据结构与算法分析这门课程理论和实践同等重要,在此次的课程设计实验,程序本身还有很多不足的地方,我自己的问题还有很多。也正因如此,我的前进的空间还很大,希望在之后的计算机相关课程中学到更多知识,提高自己的动手实践能力。
6.参考文献
[1]严蔚敏,吴伟民.数据结构(C语言版)[M].北京:清华大学出版社
[2]苏小红,孙志岗等.C语言大学实用教程[M].北京:电子工业出版社

浙公网安备 33010602011771号