据结构》.docx
《据结构》.docx》由会员分享,可在线阅读,更多相关《据结构》.docx(11页珍藏版)》请在冰豆网上搜索。
![据结构》.docx](https://file1.bdocx.com/fileroot1/2023-4/25/5afcb0d8-d612-4d56-9028-02dc5f0dc15d/5afcb0d8-d612-4d56-9028-02dc5f0dc15d1.gif)
据结构》
《数据结构》
课程设计报告
题目:
稀疏矩阵的快速转置
班级:
10网本
学号:
1107100104
姓名:
胡卫芳
完成时间:
2011年11月30日
任课教师:
邱颖豫
一、
问题描述
稀疏矩阵是指矩阵中大多数元素为零的矩阵,从直观上来讲,当非零元素个数只占矩阵元素总数的25%~30%或低于这个百分数时,这样的矩阵为稀疏矩阵。
构建稀疏矩阵,并实现稀疏矩阵的快速转置
二、程序结构
1、程序思想:
程序结构——
(1)稀疏矩阵的存储方式——三元组表表示法
对于稀疏矩阵的压缩存储,采取只存储非零元素的方法,由于稀疏矩阵中非零元素Aij的分布一般是没有规律的,因此要求在存储非零元素值的同时还必须存储该非零元素在矩阵中所处的行号和列好的位置信息,这就是稀疏矩阵的三元组表表示法。
(说明:
未处理方便,将稀疏矩阵中非零元素对应的三元组按“航虚伪朱旭”用一位结构体数组进行存放,僵局真的每一行(行由小到大)的全体非零元素的三元组按列号递增存放。
由此得到矩阵M,N的三元组表。
(2)稀疏矩阵的快速转置算法思想——
为了使转职后矩阵的三元组表B按“行序递增”存放,必须多次扫描被转置矩阵的A,以保证按被转置矩阵列序递增进行转置,因此要通过双重循环来完成。
即只对被转置矩阵的三元组表A扫描一次,就使A中所有非零元的三元组“一次定位”直接放到三元组表B的位置上。
为了能将被转至三元组表A中的元素一次定位到三元组表B的正确位置上,需要预先计算以下数据:
待转职矩阵三元组表A每一列中非零元素的总个数(即转置后矩阵三元组B的每一行中非零元素的总个数)
待转置矩阵每一列中每一个非零元素在三元组表B中的正确位置(即转置后矩阵每一行中第一个非零元素在三元组B中正确位置。
二、1)问题求解思路(算法思想)
首先需创建一个稀疏矩阵,然后按照上面所提思路,在稀疏矩阵转置算法中加设两个数组,分别为num[]和position[],其中num[col]用来存放三元组表Av中第col列中非零元素总个数(三元组表B中第col行中非零元素的总个数),position[]用来存放转置前三元组表A中第col列(转置后B中第col行)黄总第一个非零元素在三元组表B中的存储位置。
进而写出稀疏矩阵快速转职的算法。
2)主要函数:
CreatSMatrix(Tabletype*);/*生成矩阵*/
voidDestroySMatrix(Tabletype*);/*销毁矩阵*/
voidout_matrix(Tabletype*);/*打印矩阵*/
intFastTransposeSMatrix(Tabletype*,Tabletype*);/*快速转置算法*/
三、测试及结果
1、测试情况
输入126237318这样一组数据,测试其结果
2、测试结果
三、源程序
/*矩阵的快速转置*/
#include
#include
#include
#defineMAXSIZE200/*矩阵中最大非零元的个数*/
typedefstructtriple
{
inti;/*行标,本程序中从1开始的*/
intj;/*列标,本程序中从1开始的*/
inte;/*非零元*/
}Triple;/*三元组定义*/
typedefstructtabletype
{
intmu;/*矩阵的行数*/
intnu;/*列数*/
inttu;/*非零元个数*/
Tripledata[MAXSIZE];/*非零元的三元组表,本程序中是从data[1]开始使用的*/
}Tabletype;/*三元组线性表*/
/*以下为函数声明,注意和书本上的参数类型不同,我用的形参全为指针*/
voidCreatSMatrix(Tabletype*);/*生成矩阵*/
voidDestroySMatrix(Tabletype*);/*销毁矩阵*/
voidout_matrix(Tabletype*);/*打印矩阵*/
intFastTransposeSMatrix(Tabletype*,Tabletype*);/*快速转置算法*/
intmain(void)/*主函数*/
{
charch;
Tabletypea={0,0,0,{0,0,0}};/*初始化为0,便于输入数据时的无效检测*/
Tabletypeb;/*声明矩阵b*/
while
(1)
{
printf("@@@@@@@@@@@@@@本程序的功能是实现稀疏矩阵的快速转置@@@@@@@@@@@@@@@\n");
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
CreatSMatrix(&a);
printf("ThesourceMatrix:
\n");
out_matrix(&a);
if(FastTransposeSMatrix(&a,&b))/*若a不为零矩阵则转置a,存入b中*/
{printf("AfterTransposeSMatrix:
\n");
out_matrix(&b);
}
else
{
printf("Thematrixiszeros:
\n");
out_matrix(&a);
}
/*以下为程序控制*/
printf("Input'q'toquitand'c'runagain:
");
do{
if((ch=getchar())=='q'||ch=='Q')
{
DestroySMatrix(&a);
DestroySMatrix(&b);
exit(0);
}
}while((ch!
='C')&&(ch!
='c'));
system("cls");
}
return1;
}
voidCreatSMatrix(Tabletype*a)//创建矩阵
{
inti;
printf("请输入矩阵的行数、列数和非零元个数,用空格间隔:
");
scanf("%d%d%d",&(a->mu),&(a->nu),&(a->tu));
for(i=1;i<=a->tu;)
{
printf("请输入矩阵中第%d个非零元(按行标、列标、值的顺序,空格间隔):
",i);
scanf("%d%d%d",&(a->data[i].i),&(a->data[i].j),&(a->data[i].e));
if(a->data[i].i<1||a->data[i].i>a->mu||a->data[i].j<1||a->data[i].j>a->nu)/*下标越界*/
{
printf("注意:
下标越界输入数据无效!
\n请重新输入:
行标范围:
1--%d,列标范围1--%d!
!
!
\n",a->mu,a->nu);
continue;
}
if(((a->data[i].i)<(a->data[i-1].i))||
(((a->data[i].i)==(a->data[i-1].i))&&((a->data[i].j)<=(a->data[i-1].j))))/*非按行顺序输入*/
{
printf("注意:
输入数据无效!
\n请按照按行存储的顺序输入数据!
!
!
\n");
continue;
}
i++;
}
}
voidDestroySMatrix(Tabletype*a)//销毁矩阵
{/*销毁稀疏矩阵a*/
(*a).mu=0;
(*a).nu=0;
(*a).tu=0;
}
voidout_matrix(Tabletype*a)/*打印矩阵*/
{
inti,j,k=1;
for(i=1;i<=a->mu;i++)
{
for(j=1;j<=a->nu;j++)
{/*判断是否为非零元*/
if((a->data[k].i==i)&&(a->data[k].j==j))
{
printf("%4d",a->data[k].e);
k++;
}
else
printf("%4d",0);
}
printf("\n");
}
}
intFastTransposeSMatrix(Tabletype*a,Tabletype*b)//稀疏矩阵的快速转置
{
intp,q,col;
int*num;
int*cpot;
b->mu=a->nu;/*原矩阵的行数为新矩阵的列数,原列数为新行数,非零元个数不变*/
b->nu=a->mu;
b->tu=a->tu;
num=(int*)malloc((b->nu+1)*sizeof(int));/*生成两个辅助数组*/
cpot=(int*)malloc((b->nu+1)*sizeof(int));
if(b->tu)/*若a不为零矩阵*/
{
for(col=0;colnu;col++)/*初始化矩阵a的每列中非零元的个数均为0*/
num[col]=0;
for(col=0;col<=a->tu;col++)/*统计每列中非零元的个数*/
num[a->data[col].j]++;
cpot[1]=1;/*确定每列中第一个非零元的位置*/
for(col=2;col<=a->nu;col++)
cpot[col]=num[col-1]+cpot[col-1];
for(p=1;p<=a->tu;p++)/*p为a-data的下标*/
{
col=a->data[p].j;/*交换元素*/
q=cpot[col];
b->data[q].i=a->data[p].j;
b->data[q].j=a->data[p].i;
b->data[q].e=a->data[p].e;
q++;
cpot[col]++;
}
free(num);/*释放两个辅助数组*/
free(cpot);
return1;/*转置成功*/
}
else/*a为零矩阵*/
return0;
}
二、测试及结果
三、总结
通过本次实验我对数组存储有了更进一步的了解,并且通过实验又想到了快速转置的改进方法,思想是按照以下步骤计算position[col]的值:
一、初始化各position[col]的值为1,即出事家丁A中各类第一个非零元素均从B的第一个下表位置开始存放
二、循环扫描一遍矩阵A的三元组表,没遇到一个列号为col的元素,就将对应的从position[col]开始的其余元素值增1,
三、对矩阵A的三元组表到买哦一遍完成转置,当A中第col列有一个元素加入三元组表B时,则对应position[col]的值加1,是position[col]始终指向三元组表A第col列中下一个非零元素在三元组表B中的正确位置。
另外,通过编程,使我掌握稀疏矩阵的特点,存储方法和基本原理,认识到算法不再会就可以,还得会灵活运用,从而培养了我运用C语言正确编程及调试的能力,运用数据结构解决简单的实际问题的能力,为后继计算机专业课程的学习打下基础。
通过这次的实验,我学习了很多知识,也认识到了自己的不足,那就是缺乏相应的知识和经验,调试程序能力还有所欠缺,所以在运用和操作方面体现了不足。
所以在今后的学习中我会努力取得更大的进步。