一. 实验要求 用三元组表压缩存储矩阵,实现创建矩阵、显示以及教材中介绍的两种转置算法。 二. 实验目的 通过该实验,理解矩阵压缩存储的概念、方法等相关知识,掌握用三元组表方式如何进行矩阵的压缩存储,并在此基础上进行转置操作,理解转置和快速转置两种矩阵转置算法的思想。 三. 设计思想 首先,构建稀疏矩阵的三元组顺序表存储单元。一个结点的定义:假设非零元个数的最大值为125000,定义非零元的行下标j,列下标k,元素值e;还有整个三元组表的定义:数据data(数据从data[1]开始存,data[0]未用),矩阵的行数mu,列数nu和非零元个数tu。然后写出函数word()用于输出选项。 1.创建矩阵,首先从键盘输入要创建矩阵的行数mu列数nu非零元个数tu。检查非零元素个数是否小于等于行数乘列数:if(M.tu>M.mu*M.nu);然后利用for循环循环输入第i个元素的行数row,列数col和元素值e。首先检查输入的行数或者列数是否大于创建矩阵的行数或列数if(row>M.mu||col>M.nu);检查是否能控制输入的非零元素的下标是递增的:先判断行数j是否是递增的if(row<M.data[i-1].j&&i>1),注意判断递增是在输入第二个元素开始;再判断如果行数j相同、列数k是否是递增的if(row==M.data[i-1].j&&i>1){if(col<M.data[i-1].k)};//检查是否能拦截元素重复输入:if((row==M.data[i-1].j)&&(col==M.data[i-1].k))。如果均满足条件,则进行赋值:M.data[i].j=row; M.data[i].k=col; M.data[i].e=e。 2.销毁矩阵,直接将创建矩阵的行数mu列数nu非零元个数tu均赋为0。即完成销毁矩阵。 3.输出矩阵M,首先定义一个二维数组a[100][100],然后先把数组要用的部分全部赋为0:for(i=1;i<=M.mu;i++){for(j=1;j<=M.nu;j++){a[i][j]=0; }}。再利用for循环把矩阵M的值赋给二维数组a:for(i=1;i<=M.tu;i++){a[M.data[i].j][M.data[i].k] =M.data[i].e;}。然后用for循环控制输出数组a的mu行nu列:for(i=1;i<=M.mu;i++){for(j=1;j<=M.nu;j++){cout<<a[i][j]<<" ";}cout<<endl; }。 4.转置矩阵,声明一个转置矩阵T,把M的行数mu列数nu非零元个数tu赋给T的列数nu行数mu非零元个数tu。再利用for循环对M进行转置:首先利用col来控制扫描矩阵M的三元表列序进行for循环,在循环中定义一个变量n是矩阵M中的结点编号,控制n<=M的非零元个数tu进行for循环,并定义每循环完一次col循环都赋n=1,再在循环中判断矩阵M的三元组表中底n个非零元元素的列下标k是否等于正在循环的矩阵M三元组表列序col,如果相等,则开始进行转置,把矩阵M的行下标j赋给矩阵T的列下标k,把矩阵M的列下表k赋给矩阵T的行下标j:for(int col=1;col<=M.nu;col++) {for(n=1;n<=M.tu;n++){if(M.data[n].k==col) {T.data[i].j=M.data[n].k; T.data[i].k=M.data[n].j; T.data[i].e=M.data[n].e; i++;}}},即完成转置。 5.快速转置矩阵,声明一个转置矩阵T,把M的行数mu列数nu非零元个数tu赋给T的列数nu行数mu非零元个数tu。声明两个向量num和cpot,向量num[col]用于存放M中第col列中的非零元素个数,向量cpot[col]用于存放第col列的第一个非0元素的位置。先初始化M中各列的非零元素个数为0:for(col=1;col<=M.nu;col++){num[col] =0; }。再生成每列的非零元素个数向量num:for( i = 1; i <=M.tu; i ++) {col =M.data[ i ] .k ; num [col]++;},再生成每列首元位置辅助向量表cpot:cpot[1] =1; for(col=2;col<=M.nu;col++) {cpot[col]=cpot[col-1]+num[col-1] ; }。定义两个变量p和q,p指向矩阵M的data域值,q指向矩阵T的data域值。在for循环中,控制p小于等于M的非零元个数tu,把矩阵M.data中的第p个数的列下表k赋给col,查辅助向量表得到q,即M中第p个数在转置矩阵T中的位置。然后把M中第p个元素的行下标j,列下标k和元素值e赋给T中第q个元素的列下标k,行下标j和元素值e。最后修改向量表中col所在列序的值加一,以供同一列的下一个非零元素定位用。for(p=1;p<=M.tu;p++){col=M.data[p].k; q=cpot[col];T.data[q].j=M.data[p].k;T.data[q].k=M.data[p].j;T.data[q].e=M.data[p].e;++cpot[col]; }。 四. 主要源代码
#include "iostream" using namespace std; #define MAXSIZE 12500 int checkStatus=0; typedef struct { int elem_row,elem_colunm; int elem; }Triple; typedef struct { Triple data[MAXSIZE+1]; int row_count,column_count,nonzero_elem; }TSMatrix; void selectFunc(int _select); void CreatSMatrix(TSMatrix &M); void DestroySMatrix(TSMatrix &M); void PrintSMatrix(TSMatrix &M); void TransposeSMatrix(TSMatrix &M); void FastTransposeSMatrix(TSMatrix &M); static TSMatrix M; void main() { cout<<"***************************************************"<<endl; cout<<"***************** 1.创建矩阵 *****************"<<endl; cout<<"***************** 2.销毁矩阵 *****************"<<endl; cout<<"***************** 3.输出矩阵 *****************"<<endl; cout<<"***************** 4.转置矩阵 *****************"<<endl; cout<<"***************** 5.快速转置矩阵 *****************"<<endl; cout<<"***************** 6.退出 *****************"<<endl; cout<<"***************************************************"<<endl; int _select; while(1) { cout<<"请输入功能前面的数字代号:"; cin>>_select; if(!cin || _select==0 || _select>6) { cout<<"您输入的选项有误,请重新输入!"<<endl; cout<<endl; cin.clear(); cin.sync(); continue; } else { if(_select==6) { exit(1); } else { selectFunc(_select); } } cout<<endl; } system("pause"); } void selectFunc(int _select) { switch(_select) { case 1: { CreatSMatrix(M); checkStatus=1; break; } case 2: { if(checkStatus==1) { DestroySMatrix(M); checkStatus=0; } else { checkStatus=0; cout<<"尚未初始化矩阵,请先初始化!"<<endl; } break; } case 3: { if(checkStatus==1) { PrintSMatrix(M); } else { checkStatus=0; cout<<"尚未初始化矩阵,请先初始化!"<<endl; } break; } case 4: { if(checkStatus==1) { TransposeSMatrix(M); } else { checkStatus=0; cout<<"尚未初始化矩阵,请先初始化!"<<endl; } break; } case 5: { if(checkStatus==1) { FastTransposeSMatrix(M); } else { checkStatus=0; cout<<"尚未初始化矩阵,请先初始化!"<<endl; } break; } default: { cout<<"输入不合法,请重新输入!"<<endl; break; } } } void CreatSMatrix(TSMatrix &M) { int row,col,elem; cout<<"请输入要创建矩阵的行数,列数、非零元个数:"<<endl; cin>>M.row_count; cin>>M.column_count; cin>>M.nonzero_elem; if(M.nonzero_elem>M.row_count*M.column_count || M.row_count<0 || M.column_count<0 || M.nonzero_elem<0) { cout<<"非零元素个数大于行数乘列数,输入错误!"<<endl; } else { for(int after=1;after<=M.nonzero_elem;after++) { cout<<"请输入第"<<after<<"个元素的行,列,数值:"<<endl; cin>>row; cin>>col; cin>>elem; if(row>M.row_count || col>M.column_count || row<1 || col<1) { cout<<"输入有误!"<<endl; after--; } if(row<M.data[after-1].elem_row && after>1) { cout<<"请从小到大(行数)输入元素!"<<endl; after--; continue; } if(row==M.data[after-1].elem_row && after>1) { if(col<M.data[after-1].elem_colunm) { cout<<"请按照列数从小到大输入元素!"<<endl; after--; continue; } if(col>M.data[after-1].elem_colunm) { M.data[after].elem_row=row; M.data[after].elem_colunm=col; M.data[after].elem=elem; } } if((row==M.data[after-1].elem_row) && (col==M.data[after-1].elem_colunm)) { cout<<"请勿重复输入元素!"<<endl; after--; continue; } else { M.data[after].elem_row=row; M.data[after].elem_colunm=col; M.data[after].elem=elem; } } cout<<"创建矩阵成功!"<<endl; } } void DestroySMatrix(TSMatrix &M) { M.row_count=0; M.column_count=0; M.nonzero_elem=0; cout<<"销毁矩阵成功!"<<endl; } void PrintSMatrix(TSMatrix &M) { int a[100][100]; int i,j; for(i=1;i<=M.row_count;i++) { for(j=1;j<=M.column_count;j++) { a[i][j]=0; } } for(i=1;i<=M.nonzero_elem;i++) { a[M.data[i].elem_row][M.data[i].elem_colunm]=M.data[i].elem; } for(i=1;i<=M.row_count;i++) { for(j=1;j<=M.column_count;j++) { cout<<a[i][j]<<" "; } cout<<endl; } } void TransposeSMatrix(TSMatrix &M) { TSMatrix T; T.row_count=M.column_count; T.column_count=M.row_count; T.nonzero_elem=M.nonzero_elem; int before=1; int after=1; for(int col=1;col<=M.column_count;col++) { for(before=1;before<=M.nonzero_elem;before++) { if(M.data[before].elem_colunm==col) { T.data[after].elem_row=M.data[before].elem_colunm; T.data[after].elem_colunm=M.data[before].elem_row; T.data[after].elem=M.data[before].elem; after++; } } } cout<<"转置矩阵成功!"<<endl; PrintSMatrix(T); } void FastTransposeSMatrix(TSMatrix &M) { TSMatrix T; T.row_count=M.column_count; T.column_count=M.row_count; T.nonzero_elem=M.nonzero_elem; int p,q,col,*num,*cpot; num=(int *)malloc((M.column_count+1)*sizeof(int)); cpot=(int *)malloc((M.column_count+1)*sizeof(int)); if(T.nonzero_elem) { for(col=1;col<=M.column_count;col++) { num[col]=0; } for(int after=1;after<=M.nonzero_elem;after ++) { col=M.data[after].elem_colunm; num [col]++ ; } cpot[1] =1; for(col=2;col<=M.column_count;col++) { cpot[col]=cpot[col-1]+num[col-1]; } for(p=1;p<=M.nonzero_elem;p++) { col=M.data[p]. elem_colunm; q=cpot[col]; T.data[q].elem_row=M.data[p].elem_colunm; T.data[q].elem_colunm=M.data[p].elem_row; T.data[q].elem=M.data[p].elem; cpot[col]++; } } cout<<"快速转置矩阵成功!"<<endl; PrintSMatrix(T); }五. 调试与测试数据