实验6、压缩矩阵的2种转置运算

(1)实验目的

通过该实验,让学生理解矩阵压缩存储的概念、方法等相关知识,掌握用三元组表的方式如何进行矩阵的压缩存储,

并在此基础上进行转置操作,理解转置和快速转置两种矩阵转置算法的思想。

(2)实验内容

用三元组表压缩存储矩阵,实现创建矩阵、显示以及教材中介绍的两种转置算法。

(3)参考界面

  1. 创建矩阵
  2. 销毁矩阵
  3. 输出矩阵
  4. 转置矩阵
  5. 快速转置矩阵

具体要求:请认真查看测试用例

(4)验收/测试用例

创建矩阵:

检查非零元素个数是否小于等于行数乘列数;检查是否能拦截元素下标重复输入;

检查是否能控制输入的非零元素的下标是递增的(即按照行序输入,先输入小的下标,再输入较大的下标)。

输入的过程中如果有一个输入错了,不要让用户从头再把所有的输入一次,只需把刚才输入错误的,重新输入正确即可

  • 1 输入:4(行数) 4(列数) 25(非零元个数),会提示:输入错误,非零元素个数要小于等于行数乘列数,请从新输入。
  • 2 输入:4(行数) 4(列数) 5(非零元个数)
  • 3 先输入:(1,1,1) (2,3,2)
  • 4 再输入(2,3,6),会提示:输入错误,输入的下标重复,请重新输入!
  • 5 再输入(1,1,6),会提示:输入错误,输入的下标重复,请重新输入!
  • 6 继续输入(3,1,3) (3,4,5)
  • 7 再输入(3,2,9),会提示:输入错误,下标输入时要递增输入,请重新输入!
  • 8 再输入(2,3,8),会提示:输入错误,下标输入时要递增输入,请重新输入!
  • 9 最后输入(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

重点: 矩阵的转置算法

难点: 快速转置、输入时按行序非递减输入的控制

一、设计思想

  1. 矩阵的压缩适合特殊矩阵,或者说特殊矩阵的压缩才有意义,压缩就是只需存储矩阵中的非零元素到一张表,这张表字段需要有:矩阵的总行数、列数和总的元素数,以及存储元素的结构体数组。

  2. 对于结构体数组,只需要包含 该元素的 行标、列标、该元素值。

  3. 需要注意的地方是 :

    3.1. 对于矩阵规格的判断(行数、列数是否小于0)

    3.2. 对于已定矩阵输入元素位置的判断(是否越界。是否坐标重复,是否非递减)

    3.3. 对于压缩矩阵的普通转置,需要以新矩阵的第一行开始存放元素,对应着也就是以此找处于第一列、第二列、。。等的元素

    3.4. 对于快速转置,快速的关键就在于 不存在嵌套循环,也就是一次就可以把第一个非零元元素在data中的序号计算出来,对应的思想不是位置找元素,而是一次把某个元素的位置定下来。

    3.5 设置bool的标记error_flag来 判断 不合法的情况,不合法就提示重新输入,对应I–,合法就提示当前元素输入成功

  4. 对于结构体数组采用的是定长空间,所以销毁不必释放空间,只需将元素等参数置为0即可

二、源代码

# include<iostream>
# include<stdio.h>
# include<stdlib.h>
using namespace std;//压缩矩阵的转置实验 # define MAXSIZE 10000typedef  int ElemType;typedef struct{int  row;int  col;ElemType e;
}Triple; typedef struct{Triple data[MAXSIZE + 1];int hangShu;int lieShu;int eCount;
}TSMatrix;//int print_eCount = 1;// 一、函数声明
//1. 创建矩阵
void CreateTsmatrix(TSMatrix &t);//2. 销毁矩阵
void DestoryTsmatrix(TSMatrix &t); //3. 输出矩阵
void PrintTsmatrix(TSMatrix t); //4. 转置矩阵
void TransposeSMatrix(TSMatrix t,TSMatrix &t_reserve);//5. 快速转置矩阵
void FastTransposeSMatrix(TSMatrix t,TSMatrix &t_reserve);int main(){TSMatrix t;TSMatrix t_reserve;TSMatrix t_fast;
//  t.data = NULL;
//  t.data.col = 0;
//  t.data.row = 0;
//  t.data.e = 0;t.hangShu = 0;t.lieShu = 0;t.eCount = 0;t_reserve.hangShu = 0;t_reserve.lieShu = 0;t_reserve.eCount = 0;t_fast.hangShu = 0;t_fast.lieShu = 0;t_fast.eCount = 0;bool flag = true;while(flag){cout<<"☆   欢迎使用矩阵操作小程序   ☆" <<endl<<endl;cout<<"Design By 软6-司超龙-1925050351"<<endl;cout<<"==============================="<<endl;cout<<"     1. 创建矩阵"<<endl;cout<<"     2. 销毁矩阵"<<endl;cout<<"     3. 输出矩阵"<<endl;cout<<"     4. 转置矩阵"<<endl;cout<<"     5. 快速转置矩阵"<<endl<<endl;cout<<"请输入指令完成相关操作~"<<endl;cout<<"输入一个负数退出程序!"<<endl<<endl;int n;cin>>n;switch(n){case 1:system("cls"); //1.1 保证总行数为有效值 while(true){cout<<"请输入矩阵的行数:"<<endl;cin>>t.hangShu;if(t.hangShu <= 0){cout<<"输入有误!请重新输入~"<<endl;}else{break;}}//1.2 保证总列数为有效值 while(true){cout<<"请输入矩阵的列数:"<<endl;cin>>t.lieShu;if(t.lieShu <= 0){cout<<"输入有误!请重新输入~"<<endl;}else{break;}}//2. 检查不合法的矩阵元素个数 static bool flag_num = true;while(flag_num){cout<<"请输入矩阵元素的个数:"<<endl;cin>>t.eCount;if(t.eCount > t.hangShu * t.lieShu || t.eCount <= 0){cout<<"元素个数输入有误! 请重新输入~" <<endl;}else{flag_num = false;}}/*检查1:不合法的矩阵元素个数 do{if(t.eCount > t.hangShu * t.lieShu || t.eCount < 0){cout<<"你输入的矩阵元素个数有误!请重新输入~"<<endl; }else{cout<<"请输入矩阵元素的个数:"<<endl;} cin>>t.eCount;}while(t.eCount > t.hangShu * t.lieShu)*/cout<<"请输入矩阵元素的位置及值:(元素下标不能重复,且下标需要递增)"<<endl;for(int i = 1;i<=t.eCount;i++){cin>>t.data[i].row>>t.data[i].col>>t.data[i].e;//3.1.1 对第一个元素位置单独处理 if(i == 1) {if(t.data[i].row > t.hangShu || t.data[i].col > t.lieShu || t.data[i].row <= 0 || t.data[i].col <= 0){cout<<"元素位置不合法!请重新输入第一个元素~"<<endl;i--;}//3.1.2 第一个元素成功输入 else if(i == 1){cout<<"第 " <<i<<" 个元素输入完成!共 "<<t.eCount<<" 个元素"<<endl;} }//3.1.3 从第二个元素需要处理是否有重复位置的情况 int j;//作用域需要提升 bool error_flag = false;if(i > 1){for(j = 1;j<i;j++){if(t.data[i].row == t.data[j].row && t.data[i].col == t.data[j].col ){cout<<"元素下标重复!请重新输入当前元素~"<<endl;i--;error_flag = true;break;}else if(t.data[i].row < t.data[j].row && t.data[i].col < t.data[j].col){cout<<"元素下标非递增!请重新输入当前元素~"<<endl;i--;error_flag = true;break;}else if(t.data[i].col < t.data[j].col && t.data[i].row == t.data[j].row){cout<<"元素列下标非递增!请重新输入当前元素~"<<endl;i--;error_flag = true;break;}else if(t.data[i].row < t.data[j].row ){cout<<"元素行下标非递增!请重新输入当前元素~"<<endl;i--;error_flag = true;break;}else if(t.data[i].row > t.hangShu || t.data[i].col > t.lieShu || t.data[i].row <= 0 || t.data[i].col <= 0 ) {cout<<"元素位置不合法!请重新输入当前元素"<<endl;i--; error_flag = true;break;}}}//3.1.4 除第一个元素的输入成功信息 if(!error_flag && i != 1){cout<<"第 " <<i<<" 个元素输入完成!共 "<<t.eCount<<" 个元素"<<endl;}}cout<<endl;break;case 2:system("cls");DestoryTsmatrix(t); DestoryTsmatrix(t_reserve);cout<<"矩阵销毁成功!"<<endl;cout<<endl;break;case 3:system("cls");cout<<"矩阵的元素为:"<<endl;//注意局部变量不能定义在switch中,会报错 ,需要加上static关键字 static int print_eCount = 1;for(int i = 0;i<t.hangShu;i++){for(int j = 0;j<t.lieShu;j++){if( (i + 1 == t.data[print_eCount].row) && (j + 1 == t.data[print_eCount].col) ){cout<<t.data[print_eCount].e<<" ";print_eCount++;}else{cout<<"0 ";}}cout<<endl;}cout<<endl;break;case 4:system("cls") ;TransposeSMatrix(t,t_reserve);cout<<"转置矩阵的元素为:"<<endl;PrintTsmatrix(t_reserve);cout<<endl;break;case 5:system("cls");cout<<"快速转置矩阵的元素为:"<<endl; FastTransposeSMatrix(t,t_fast);PrintTsmatrix(t_fast);cout<<endl;break;default:if(n < 0){system("cls");flag = false;cout<<"退出程序成功 ! 欢迎下次使用~~"<<endl;}else{cout<<"输入的操作指令有误!下次吧~下次吧~"<<endl;}cout<<endl;break;}}} //二、函数实现//因为输出语句不能放在功能函数,为了实现简单,部分功能函数不在单独写出
//1. 创建矩阵
void CreateTsmatrix(TSMatrix &t){} //2. 销毁矩阵
void DestoryTsmatrix(TSMatrix &t){for(int i = 1;i<=t.eCount;i++){t.data[i].e = 0;t.data[i].row = 0;t.data[i].col = 0;}t.hangShu = 0;t.lieShu = 0;t.eCount = 0;}//3. 输出矩阵
void PrintTsmatrix(TSMatrix t){int print_eCount = 1;for(int i = 0;i<t.hangShu;i++){for(int j = 0;j<t.lieShu;j++){if( (i + 1 == t.data[print_eCount].row) && (j + 1 == t.data[print_eCount].col) ){cout<<t.data[print_eCount].e<<" ";print_eCount++;}else{cout<<"0 ";}}cout<<endl;}
}//4. 转置矩阵
void TransposeSMatrix(TSMatrix t,TSMatrix &t_reserve){t_reserve.eCount = t.eCount;t_reserve.hangShu = t.lieShu;t_reserve.lieShu = t.hangShu;//矩阵中有元素 if(t_reserve.eCount){//遍历矩阵中的每个元素 先找位置 int q = 1;//从旧矩阵的第一列开始 ,现在的第一列,就是转置后的第一行 for(int i = 1;i<=t.lieShu;i++){//遍历找到每个元素 ,找到就行、列坐标互换,没找到就接着找第二列 for(int j = 1;j<=t.eCount;j++){//找到了 if(t.data[j].col == i ){t_reserve.data[q].row = t.data[j].col;t_reserve.data[q].col = t.data[j].row;t_reserve.data[q].e = t.data[j].e;//找下一个元素 q++;} }}}}//5. 快速转置矩阵
void FastTransposeSMatrix(TSMatrix t,TSMatrix &t_reserve){t_reserve.eCount = t.eCount;t_reserve.hangShu = t.lieShu;t_reserve.lieShu = t.hangShu;//开辟数组num[i]存放 原矩阵中对应第 i 列的非零元的个数,也就是转置之后第 i 行的非零元元素个数 int num[99];//开辟数组copt[col]存放的是 原矩阵col 列,也就是转置矩阵的第col行 第一个非零元在压缩矩阵中的位置 int cpot[99];if(t_reserve.eCount){//求每一列中非零元的个数 //先确定需要使用多少个num[] for(int i = 1;i<=t.lieShu;i++){num[i] = 0;}//遍历每个数的列坐标,统计列坐标相等元素的个数到num[]中//如num[1] = 1 表示原来的第一列,也就是转置后的第一行 有 1个元素 for(int j = 1;j<=t.eCount;j++){num[t.data[j].col]++;}//设置第一行第一个非零元的位置序号为1 cpot[1] = 1;//对于num[i>1] 即某一列 非零元的个数大于1的 需要定 第一个非零元素得位置 for(int m = 2;m<=t.lieShu;m++){cpot[m] = cpot[m - 1] + num[m - 1];//cpot[m] 为 每一行 第一个非零元素的序号值 } for(int n = 1;n<=t.eCount;n++){//遍历每个元素//p为该元素所在列值 ,以后如果再次出现相同的列值得元素,就cpot[p]++,序号位置++ //根据列值求在data中的序号 int p = t.data[n].col;//q对应的是序号 int q = cpot[p];t_reserve.data[q].row = t.data[n].col;t_reserve.data[q].col = t.data[n].row;t_reserve.data[q].e = t.data[n].e;cpot[p]++;}}} 

三、部分实验截图









三、实验小结

  1. 练习了特殊矩阵的定长存储方式,熟悉实现了压缩矩阵的普通转置和快速转置算法
  2. 快速转置的算法 之所以快,时间复杂度由普通的O(n^2)转化为O(n),因为避免了循环嵌套,一般的转置算法思想是依次填充位置,每个位置而必须遍历判断每个元素。而升级的转置算法是 计算出 每行第一个非零元素的data下标序号(第一行第一个则为data[1]),当填上每行第一个非零元素的位置后,存放序号的cpot[i]就加一,之后再出现该行的元素依次放入即可

数据结构实验6_压缩矩阵的转置、普通转置、快速转置算法相关推荐

  1. 数据结构-数组与压缩矩阵

    数组的定义 数组是由n(n>1)个具有相同数据类型的数据元素a1...an组成的有序序列,且该序列必须存储在一块地址连续的存储单元中. 1.数组中的数组元素就有相同的数据类型 2.数组是一种随机 ...

  2. 【swjtu】数据结构实验6_二叉树的遍历算法

    实验内容及要求: 编写程序,用先序递归遍历法建立二叉树的二叉链表存储结构,然后输出其先序.中序.后序以及层次遍历结点访问次序.其中层次遍历的实现需使用循环队列.二叉树结点数据类型建议选用字符类型. 实 ...

  3. 三元组顺序表表示的稀疏矩阵加法_数据结构实验题(三元组顺序表表示的稀疏矩阵转置运算)...

    题目描述: 思路: 先用三元顺序表存放稀疏矩阵 typedef struct{ int row, col; int elem;} Elem;typedef struct{ int Row, Col, ...

  4. 6-7 拓扑排序 (10分)_数据结构实验6_羊卓的杨

    6-7 拓扑排序 (10分) 试实现拓扑排序算法.函数void FindInDegree(ALGraph G,int indegree[])实现图中各个顶点入度的统计:函数int Topologica ...

  5. e - 数据结构实验之查找五:平方之哈希表_leetcode算法之哈希表

    今天该来盘一盘 哈希表 这类题目 分类别解析leetcode上的一些相关的例题路,代码采用C++与python实现. 哈希表 哈希表是一种很有用的数据结构, 其作用主要是以空间换时间, 在c++中主要 ...

  6. java三元组的快速转置_矩阵压缩——三元组以及矩阵快速转置程序实现

    一.问题描述 将一个稀疏矩阵,用三元组的方式压缩存储,然后实现其快速转置 二.实验源码 #include #include #define Size 100 typedef struct { int ...

  7. 数据结构实验之数组一:矩阵转置

    数据结构实验之数组一:矩阵转置 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Problem Description 数组- ...

  8. 数组:矩阵快速转置 矩阵相加 三元组顺序表/三元矩阵 随机生成稀疏矩阵 压缩矩阵【C语言,数据结构】(内含源代码)

    目录 题目: 题目分析: 概要设计: 二维矩阵数据结构: 三元数组\三元顺序表顺序表结构: 详细设计: 三元矩阵相加: 三元矩阵快速转置: 调试分析: 用户手册: 测试结果: 源代码: 主程序: 头文 ...

  9. c++矩阵转置_C语言:数据结构-稀疏矩阵的压缩存储

    (1)稀疏矩阵的特点 在一个m×n的矩阵中,设矩阵中有i个元素不为零,并令△=i/(m×n),称△为稀疏因子.通常当△≤0.05时.认为该矩阵为稀疏矩阵. 对这类矩阵实现压缩存储的基本思路是只需要存储 ...

最新文章

  1. 【CV】吴恩达机器学习课程笔记 | 第1-15章
  2. Error in contrasts can be applied only to factors with 2 or more levels
  3. Linux系统工程师的必备素质
  4. 从Java代码到Java堆理解和优化您的应用程序的内存使用
  5. Leetcode 90. 子集 II 解题思路及C++实现
  6. 小米自动化运维平台演进设计思路
  7. 详谈Windows消息循环机制
  8. 【渝粤教育】国家开放大学2019年春季 4有机合成单元反应 参考试题
  9. 访问订单列表时报错404
  10. bzoj1189 [HNOI2007]紧急疏散EVACUATE spfa+网络流+二分
  11. Zabbix对接AD域
  12. android系统签名
  13. CentOS6.5下安装mfs分布式存储(转)
  14. linux网站配置文件.htaccess伪静态转换到IIS web.config中
  15. 日志分析的大救星 — — 集算器
  16. 产品文档 | PRD写作手册
  17. idea显示前进和后退按钮
  18. excel入门/常用的技巧
  19. 人脸识别-批量裁剪图像
  20. windows微信多开,超便捷的使用方式,真正一劳永逸的方法

热门文章

  1. 思想一年一年进步才好
  2. 用c语言实现三子棋,它来了!!
  3. 为啥功放上的音量控制的dB数都是负的
  4. OLAP、OLTP的介绍和比较
  5. 动态规划(Dynamic Programming)
  6. Blockchain Empowered Asynchronous Federated Learning for Secure Data Sharing in IoV
  7. WinXP SP2发布以来的所有补丁集下载 0812(V1.3.0)[119M]
  8. 什么是SSH 以及常见的ssh 功能
  9. c#.net command 命令详细分析
  10. 上位机命名规范驼峰命名法和下划线命名法