数据结构实验6_压缩矩阵的转置、普通转置、快速转置算法
实验6、压缩矩阵的2种转置运算
(1)实验目的
通过该实验,让学生理解矩阵压缩存储的概念、方法等相关知识,掌握用三元组表的方式如何进行矩阵的压缩存储,
并在此基础上进行转置操作,理解转置和快速转置两种矩阵转置算法的思想。
(2)实验内容
用三元组表压缩存储矩阵,实现创建矩阵、显示以及教材中介绍的两种转置算法。
(3)参考界面
- 创建矩阵
- 销毁矩阵
- 输出矩阵
- 转置矩阵
- 快速转置矩阵
具体要求:请认真查看测试用例
(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
重点: 矩阵的转置算法
难点: 快速转置、输入时按行序非递减输入的控制
一、设计思想
矩阵的压缩适合特殊矩阵,或者说特殊矩阵的压缩才有意义,压缩就是只需存储矩阵中的非零元素到一张表,这张表字段需要有:矩阵的总行数、列数和总的元素数,以及存储元素的结构体数组。
对于结构体数组,只需要包含 该元素的 行标、列标、该元素值。
需要注意的地方是 :
3.1. 对于矩阵规格的判断(行数、列数是否小于0)
3.2. 对于已定矩阵输入元素位置的判断(是否越界。是否坐标重复,是否非递减)
3.3. 对于压缩矩阵的普通转置,需要以新矩阵的第一行开始存放元素,对应着也就是以此找处于第一列、第二列、。。等的元素
3.4. 对于快速转置,快速的关键就在于 不存在嵌套循环,也就是一次就可以把第一个非零元元素在data中的序号计算出来,对应的思想不是位置找元素,而是一次把某个元素的位置定下来。
3.5 设置bool的标记error_flag来 判断 不合法的情况,不合法就提示重新输入,对应I–,合法就提示当前元素输入成功
对于结构体数组采用的是定长空间,所以销毁不必释放空间,只需将元素等参数置为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]++;}}}
三、部分实验截图
三、实验小结
- 练习了特殊矩阵的定长存储方式,熟悉实现了压缩矩阵的普通转置和快速转置算法
- 快速转置的算法 之所以快,时间复杂度由普通的O(n^2)转化为O(n),因为避免了循环嵌套,一般的转置算法思想是依次填充位置,每个位置而必须遍历判断每个元素。而升级的转置算法是 计算出 每行第一个非零元素的data下标序号(第一行第一个则为data[1]),当填上每行第一个非零元素的位置后,存放序号的cpot[i]就加一,之后再出现该行的元素依次放入即可
数据结构实验6_压缩矩阵的转置、普通转置、快速转置算法相关推荐
- 数据结构-数组与压缩矩阵
数组的定义 数组是由n(n>1)个具有相同数据类型的数据元素a1...an组成的有序序列,且该序列必须存储在一块地址连续的存储单元中. 1.数组中的数组元素就有相同的数据类型 2.数组是一种随机 ...
- 【swjtu】数据结构实验6_二叉树的遍历算法
实验内容及要求: 编写程序,用先序递归遍历法建立二叉树的二叉链表存储结构,然后输出其先序.中序.后序以及层次遍历结点访问次序.其中层次遍历的实现需使用循环队列.二叉树结点数据类型建议选用字符类型. 实 ...
- 三元组顺序表表示的稀疏矩阵加法_数据结构实验题(三元组顺序表表示的稀疏矩阵转置运算)...
题目描述: 思路: 先用三元顺序表存放稀疏矩阵 typedef struct{ int row, col; int elem;} Elem;typedef struct{ int Row, Col, ...
- 6-7 拓扑排序 (10分)_数据结构实验6_羊卓的杨
6-7 拓扑排序 (10分) 试实现拓扑排序算法.函数void FindInDegree(ALGraph G,int indegree[])实现图中各个顶点入度的统计:函数int Topologica ...
- e - 数据结构实验之查找五:平方之哈希表_leetcode算法之哈希表
今天该来盘一盘 哈希表 这类题目 分类别解析leetcode上的一些相关的例题路,代码采用C++与python实现. 哈希表 哈希表是一种很有用的数据结构, 其作用主要是以空间换时间, 在c++中主要 ...
- java三元组的快速转置_矩阵压缩——三元组以及矩阵快速转置程序实现
一.问题描述 将一个稀疏矩阵,用三元组的方式压缩存储,然后实现其快速转置 二.实验源码 #include #include #define Size 100 typedef struct { int ...
- 数据结构实验之数组一:矩阵转置
数据结构实验之数组一:矩阵转置 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Problem Description 数组- ...
- 数组:矩阵快速转置 矩阵相加 三元组顺序表/三元矩阵 随机生成稀疏矩阵 压缩矩阵【C语言,数据结构】(内含源代码)
目录 题目: 题目分析: 概要设计: 二维矩阵数据结构: 三元数组\三元顺序表顺序表结构: 详细设计: 三元矩阵相加: 三元矩阵快速转置: 调试分析: 用户手册: 测试结果: 源代码: 主程序: 头文 ...
- c++矩阵转置_C语言:数据结构-稀疏矩阵的压缩存储
(1)稀疏矩阵的特点 在一个m×n的矩阵中,设矩阵中有i个元素不为零,并令△=i/(m×n),称△为稀疏因子.通常当△≤0.05时.认为该矩阵为稀疏矩阵. 对这类矩阵实现压缩存储的基本思路是只需要存储 ...
最新文章
- 【CV】吴恩达机器学习课程笔记 | 第1-15章
- Error in contrasts can be applied only to factors with 2 or more levels
- Linux系统工程师的必备素质
- 从Java代码到Java堆理解和优化您的应用程序的内存使用
- Leetcode 90. 子集 II 解题思路及C++实现
- 小米自动化运维平台演进设计思路
- 详谈Windows消息循环机制
- 【渝粤教育】国家开放大学2019年春季 4有机合成单元反应 参考试题
- 访问订单列表时报错404
- bzoj1189 [HNOI2007]紧急疏散EVACUATE spfa+网络流+二分
- Zabbix对接AD域
- android系统签名
- CentOS6.5下安装mfs分布式存储(转)
- linux网站配置文件.htaccess伪静态转换到IIS web.config中
- 日志分析的大救星 — — 集算器
- 产品文档 | PRD写作手册
- idea显示前进和后退按钮
- excel入门/常用的技巧
- 人脸识别-批量裁剪图像
- windows微信多开,超便捷的使用方式,真正一劳永逸的方法
热门文章
- 思想一年一年进步才好
- 用c语言实现三子棋,它来了!!
- 为啥功放上的音量控制的dB数都是负的
- OLAP、OLTP的介绍和比较
- 动态规划(Dynamic Programming)
- Blockchain Empowered Asynchronous Federated Learning for Secure Data Sharing in IoV
- WinXP SP2发布以来的所有补丁集下载 0812(V1.3.0)[119M]
- 什么是SSH 以及常见的ssh 功能
- c#.net command 命令详细分析
- 上位机命名规范驼峰命名法和下划线命名法