作者说:
1.这个实验在数据结构课本P97 ~ P100,难点在矩阵的快速转置、输入时按行序非递减输入的控制。
2.在进行快速转置的时候,要提前知道两点:
一、非零元素的个数;
二、每一列非零元素的位置。
一、运行效果截图
二、实验要求
(1)实验目的
通过该实验,让学生理解矩阵压缩存储的概念、方法等相关知识,掌握用三元组表的方式如何进行矩阵的压缩存储,并在此基础上进行转置操作,理解转置和快速转置两种矩阵转置算法的思想。
(2)实验内容
用三元组表压缩存储矩阵,实现创建矩阵、显示以及教材中介绍的两种转置算法。
(3)参考界面
1.创建矩阵
2.销毁矩阵
3.输出矩阵
4.转置矩阵
5.快速转置矩阵
具体要求:请认真查看测试用例
(4)验收/测试用例
-
创建矩阵:
注意:检查非零元素个数是否小于等于行数乘列数;检查是否能拦截元素下标重复输入;检查是否能控制输入的非零元素的下标是递增的(即按照行序输入,先输入小的下标,再输入较大的下标)。
注意:输入的过程中如果有一个输入错了,不要让用户从头再把所有的输入一次,只需把刚才输入错误的,重新输入正确即可。
-
输入:4(行数) 4(列数) 25(非零元个数),会提示:输入错误,非零元素个数要小于等于行数乘列数,请从新输入。
-
输入:4(行数) 4(列数) 5(非零元个数)
-
先输入:(1,1,1) (2,3,2)
-
再输入(2,3,6),会提示:输入错误,输入的下标重复,请重新输入!
-
再输入(1,1,6),会提示:输入错误,输入的下标重复,请重新输入!
-
继续输入(3,1,3) (3,4,5)
-
再输入(3,2,9),会提示:输入错误,下标输入时要递增输入,请重新输入!
-
再输入(2,3,8),会提示:输入错误,下标输入时要递增输入,请重新输入!
-
最后输入(4,2,4)
- 显示
屏幕上输出:
1 0 0 0
0 0 2 0
3 0 0 5
0 4 0 0
- 转置
屏幕上输出:
1 0 3 0
0 0 0 4
0 2 0 0
0 0 5 0
三、代码示例
#include<iostream>
#include<stdlib.h>
#define maxsize 52100 //假设非零元个数的最大值为52100。
using namespace std;
typedef int Elemtype;
typedef struct{
int i,j; //非零元的行下标和列下标。
Elemtype e;
}Triple;
typedef struct{
Triple data[maxsize+1]; //非零元三元组表,data[0]未用。
int mu,nu,tu; //矩阵的行数、列数和非零元素的个数。
}TSMatrix;
void CreateSMatrix(TSMatrix &T);//1.创建矩阵
void DestorySMatrix(TSMatrix &T);//2.销毁矩阵
void PrintSMatrix(TSMatrix T);//3.输出矩阵
void TransposeSMatrix(TSMatrix T,TSMatrix &Ts);//4.转置矩阵
void FastTransposeSMatrix(TSMatrix T,TSMatrix &Ts);//5.快速转置矩阵
int main()
{
TSMatrix T,Ts;
T.mu=T.nu=T.tu=0;
Ts.mu=Ts.nu=Ts.tu=0;
int xuanze,in=999,cunzai=0;
cout<<endl;
cout<<"☆☆☆欢迎使用压缩矩阵小程序☆☆☆"<<endl;
cout<<"author---Henan University.software engineering.李思佳"<<endl<<endl;
while(in==999)
{
cout<<"1.创建矩阵"<<endl;
cout<<"2.销毁矩阵"<<endl;
cout<<"3.输出矩阵"<<endl;
cout<<"4.转置矩阵"<<endl;
cout<<"5.快速转置矩阵"<<endl;
cout<<"☆☆☆退出,输入一个负数!☆☆☆"<<endl<<endl;
cout<<"请输入您的选择:";
cin>>xuanze;
switch(xuanze)
{
case 1:
system("cls");
CreateSMatrix(T);//1.创建矩阵
cunzai=1;
cout<<endl;
break;
case 2:
system("cls");
if(cunzai==1)
{
DestorySMatrix(T);//2.销毁矩阵
cout<<"矩阵销毁成功!"<<endl;
cunzai=0;
}
else
{
cout<<"还未创建一个矩阵,无法销毁!"<<endl;
}
cout<<endl;
break;
case 3:
system("cls");
if(cunzai==1)
{
PrintSMatrix(T);//3.输出矩阵
}
else
{
cout<<"还未创建一个矩阵,无法输出!"<<endl;
}
cout<<endl;
break;
case 4:
system("cls");
if(cunzai==1)
{
TransposeSMatrix(T,Ts);//4.转置矩阵
PrintSMatrix(Ts);
}
else
{
cout<<"还未创建一个矩阵,无法转置!"<<endl;
}
cout<<endl;
break;
case 5:
system("cls");
if(cunzai==1)
{
FastTransposeSMatrix(T,Ts);//5.快速转置矩阵
PrintSMatrix(Ts);
}
else
{
cout<<"还未创建一个矩阵,无法快速转置!"<<endl;
}
cout<<endl;
break;
default:
system("cls");
if(xuanze<0)
{
cout<<"☆☆☆您已经退出程序,欢迎下次使用!☆☆☆"<<endl;
in=-999;
}
else
{
cout<<"选择有误,请重新输入选择!"<<endl;
}
break;
}
}
}
//1.创建矩阵
void CreateSMatrix(TSMatrix &T)
{
int n=1;
cout<<"您正在创建一个矩阵~"<<endl;
while(1)//输入矩阵行数mu。
{
cout<<"请输入矩阵行数:";
cin>>T.mu;
if(T.mu<=0)
{
cout<<"您输入的行数有误,请重新输入!"<<endl<<endl;
}
else
{
cout<<"输入成功!"<<endl;
break;
}
}
while(1)//输入矩阵列数。
{
cout<<"请输入矩阵列数:";
cin>>T.nu;
if(T.nu<=0)
{
cout<<"您输入的列数有误,请重新输入!"<<endl<<endl;
}
else
{
cout<<"输入成功!"<<endl;
break;
}
}
while(1)//输入非零元素个数。
{
cout<<"请输入非零元素个数:";
cin>>T.tu;
if(T.tu > T.mu*T.nu)
{
cout<<"您输入的个数不符合要求,要输入一个小于或等于行数乘列数的值,请重新输入!"<<endl<<endl;
}
else
{
cout<<"输入成功!"<<endl<<endl;
break;
}
}
cout<<"矩阵的行数为:"<<T.mu<<endl;
cout<<"矩阵的列数为:"<<T.nu<<endl;
cout<<"矩阵的非零元素个数为:"<<T.tu<<endl<<endl;
cout<<"开始输入非零元素啦!"<<endl;
cout<<"(提示:输入1 1 1代表第一行第一列值为1的元素,下标不要重复输入,下标按行序递增输入)" <<endl;
while(n<=T.tu)//判断不合法的情况,给出提示语句。
{
cout<<endl;
cout<<"请按照提示输入非零元素:";
int shuru=1;
cin>>T.data[n].i>>T.data[n].j>>T.data[n].e;
for(int p=1;p<n;p++)
{
if(T.data[n].i==T.data[p].i&&T.data[n].j==T.data[p].j)
{//检查元素下标是否重复输入。
cout<<"输入错误,您输入的下标重复了,请重新输入!"<<endl;
shuru=0;
break;
}
else if(T.data[n].e==0)
{
cout<<"输入错误,您需要输入元素的值不为零,请重新输入!"<<endl;
shuru=0;
break;
}
else if(T.data[n].i==0||T.data[n].j==0)
{
cout<<"输入错误,您输入的下标不合法,请重新输入!"<<endl;
shuru=0;
break;
}
else if(T.data[n].i>T.mu||T.data[n].j>T.nu)//检查下标是否越界。
{
cout<<"输入错误,您输入的元素下标越界,请重新输入!"<<endl<<endl;
shuru=0;
break;
}
else if(n>1&&T.data[n].i<T.data[n-1].i)//检查下标是否递增。
{
cout<<"输入错误,输入的行下标非递增,请重新输入!"<<endl<<endl;
shuru=0;
break;
}
else if(n>1&&T.data[n].i==T.data[n-1].i&&T.data[n].j<T.data[n-1].j)
{
cout<<"输入错误,输入的列下标非递增,请重新输入!"<<endl<<endl;
shuru=0;
break;
}
}
if(shuru==1)
{
cout<<"您成功输入了元素:("<<T.data[n].i<<","<<T.data[n].j<<","<<T.data[n].e<<"),矩阵共"<<T.tu<<"个元素。"<<endl;
n++;
}
}
cout<<endl;
cout<<"您已经成功创建了一个矩阵!"<<endl;
}
//2.销毁矩阵
void DestorySMatrix(TSMatrix &T)
{
//依次将三元组表中的数据置0,将非零元个数、总行数、总列数置0。
for(int p=1;p<=T.tu;p++)
{
T.data[p].i=0;
T.data[p].j=0;
T.data[p].e=0;
}
T.mu=0;
T.nu=0;
T.tu=0;
}
//3.输出矩阵
void PrintSMatrix(TSMatrix T)
{
//类似于二维数组的输出,但是存储结构是一维数组,需要匹配到正确的位置。
//有非零元的位置输入其值,没有非零元的位置输入0。
for(int a=1,p=1;a<=T.mu;a++)
{
for(int b=1;b<=T.nu;b++)
{
if(T.data[p].i==a&&T.data[p].j==b)
{
cout<<T.data[p].e<<" ";
p++;
}
else
{
cout<<0<<" ";
}
}
cout<<endl;
}
}
//4.转置矩阵
void TransposeSMatrix(TSMatrix T,TSMatrix &Ts)
{
//采用采用三元组表存储表示,求稀疏矩阵T的转置矩阵Ts。
Ts.mu=T.nu;
Ts.nu=T.mu;
Ts.tu=T.tu;
if(Ts.tu)
{
int p=1;
for(int a=1;a<=T.nu;a++)//控制列数,T的列值会成为Ts的行值。
{
for(int b=1;b<=T.tu;b++)//遍历,把T中的每一个非零元都查询一遍。
{
if(T.data[b].j==a)
//找到T中列值等于此时Ts中的行值的非零元,并把位置和值赋给Ts中相应位置。
{
Ts.data[p].i=T.data[b].j;
Ts.data[p].j=T.data[b].i;
Ts.data[p].e=T.data[b].e;
p++;
}
}
}
}
}
//5.快速转置矩阵
void FastTransposeSMatrix(TSMatrix T,TSMatrix &Ts)
{
//采用采用三元组表存储表示,求稀疏矩阵T的转置矩阵Ts。
Ts.mu=T.nu;
Ts.nu=T.mu;
Ts.tu=T.tu;
int num[100];//num[n]表示矩阵T中第n列中非零元的个数。
int cpot[100];//cpot[n]表示矩阵T中第n列中第一个非零元在Ts顺序表中的位置。
if(T.tu)
{
int n;
for(n=1;n<=T.mu;n++)//给num赋值。
{
num[n]=0;
}
for(n=1;n<=T.tu;n++)//求T中每一列的非零元个数。
{
num[T.data[n].j]++;
}
cpot[1]=1;
for(n=2;n<=T.mu;n++)//求第n列中第一个非零元在Ts中的位置。
{
cpot[n]=cpot[n-1]+num[n-1];
}
for(int p=1;p<=T.tu;p++)//开始转置,将T中的非零元赋给Ts。
{
n=T.data[p].j;
int q=cpot[n];
Ts.data[q].i=n;
Ts.data[q].j=T.data[p].i;
Ts.data[q].e=T.data[p].e;
cpot[n]++;
}
}
}