目录

1.三元组表的定义

2.三元组表的数据结构

3.三元组表的构建

4.输出三元组表

5.两个三元组表相加

代码的流程图​

实现代码

6.三元组表的快速转置

算法思想

代码实现

7.三元组表输出矩阵

8.全部代码

9.总结


1.三元组表的定义

三元组研究目的 对于在实际问题中出现的大型的稀疏矩阵,若用常规分配方法在计算机中储存,将会产生大量的内存浪费,而且在访问和操作的时候也会造成大量时间上的浪费,为了解决这一问题,从而产生了多种解决方案。 由于其自身的稀疏特性,通过压缩可以大大节省稀疏矩阵的内存代价。

        主要是用来存储 稀疏矩阵 的一种压缩方式,也叫三元组表。 假设以顺序 存储结构 来表示三元组表(triple table),则得到 稀疏矩阵 的一种压缩存储方式,即三元组顺序表,简称三元组表。

2.三元组表的数据结构

#define MAX 1000typedef struct
{int row,col,e;    //数据所在的行、列,数值
}Triple;typedef struct
{Triple  data[MAX+1];int mu,nu,tu;     //矩阵的行数,列数和非零元个数
}TSMatrix;

3.三元组表的构建

思路:从第一行开始遍历查找非零元素,存入三元组表data[tu]中,data[tu].row=i,data[tu].col=j,data[tu].e=a[i][j]

void input(TSMatrix *p,int m,int n)
{int i,j;int a[100][100];for( i=1;i<=m;i++)    //随机生成稀疏矩阵for(j=1;j<=n;j++){if(1+rand()%4>=1+rand()%19)a[i][j]=1+rand()%99;elsea[i][j]=0;}for(int i=1;i<=m;i++){    //打印出该稀疏矩阵for(int j=1;j<=n;j++){printf("%4d",a[i][j]);}printf("\n");}p->tu=0;    //三元组表的总个数for(i=1;i<=m;i++)    //进行查找非零元素进行存储for(j=1;j<=n;j++){if(a[i][j]!=0){p->data[p->tu].row=i;  //行p->data[p->tu].col=j; //列p->data[p->tu].e=a[i][j]; //  数据++p->tu;}}}

4.输出三元组表

void printTriple(TSMatrix *p)
{printf("\n三元组:\n");for(int i=0;i<p->tu;i++){printf("%4d %4d %4d\n",p->data[i].row,p->data[i].col,p->data[i].e);}
}

5.两个三元组表相加

思路:两个三元组分别标记两个遍历用的i,j,每次都比较i和j所在位置的row、col值;先比较row的大小,如果i的row小于j的,那就先填i的,然后i++填下一个;如果i和j的row都相同,就去比col,然后i的col小于j,者填i,否则填j的。

如果A与B的row和col都相同,就把row和col分别相加,再存入C中

如果i遍历完,j没遍历完,把j剩余的全放入新的三元组表中;如果i没遍历完,j遍历完,把i剩余的全放入新的三元组表中。

通俗的解释:这个就类似于小编之前的写的顺序表和合并的思路。大家也可以回顾一下两个顺序表的合并思路,联系起来。数据结构:两个顺序表合并算法_业余小程序猿的博客-CSDN博客

注意:只有两个相同行列的矩阵才能相加,所以相加之前要先判断一下能不能。

代码的流程图

实现代码


void sum(TSMatrix *A,TSMatrix *B,TSMatrix *C)
{C->mu=A->mu;    //只有两个行列相同的矩阵才能相加C->nu=A->nu;    //所以用A或B都一样C->tu=0;if(A->mu!=B->mu&&A->nu!=B->nu){printf("矩阵要大小相同才能相加!");return ;}int i=0,j=0;while(i<A->tu&&j<B->tu){if(A->data[i].row<B->data[j].row)    //A的row<B的,C中加入A的{C->data[C->tu].row=A->data[i].row;   //行C->data[C->tu].col=A->data[i].col; //列C->data[C->tu].e=A->data[i].e; //  数据C->tu++;i++;}else if(A->data[i].row==B->data[j].row)    //A的row=B的,再继续比较col{if(A->data[i].col<B->data[j].col)    //A的col<B的,C中加入A的{C->data[C->tu].row=A->data[i].row; //行C->data[C->tu].col=A->data[i].col; //列C->data[C->tu].e=A->data[i].e; //  数据C->tu++;i++;           }else if(A->data[i].col>B->data[j].col) //A的col>B的,C中加入B的{C->data[C->tu].row=B->data[j].row;   //行C->data[C->tu].col=B->data[j].col; //列C->data[C->tu].e=B->data[j].e; //  数据C->tu++;j++;}else    //A的col=B的,先把A和B的row和col分别相加,再存入C中{if(B->data[j].e+A->data[i].e!=0){C->data[C->tu].row=B->data[j].row;   //行C->data[C->tu].col=B->data[j].col; //列C->data[C->tu].e=B->data[j].e; //  数据C->tu++;}i++;j++;}}else    //A的row>B的,C中加入B的{C->data[C->tu].row=B->data[j].row;  //行C->data[C->tu].col=B->data[j].col; //列C->data[C->tu].e=B->data[j].e; //  数据C->tu++;j++;           }}while(i<A->tu)//如果A剩余,把A剩余的全放入C中{C->data[C->tu].row=A->data[i].row;    //行C->data[C->tu].col=A->data[i].col; //列C->data[C->tu].e=A->data[i].e; //  数据C->tu++;i++;       }while(j<B->tu)//如果B剩余,把B剩余的全放入C中{C->data[C->tu].row=B->data[j].row; //行C->data[C->tu].col=B->data[j].col; //列C->data[C->tu].e=B->data[j].e; //  数据C->tu++;j++;}}

6.三元组表的快速转置

转置定义:将矩阵的行列互换得到的新矩阵称为转置矩阵,转置矩阵的行列式不变。

算法思想

矩阵的转置就是讲行列互换位置,如果普通两层循环进行循环的,时间复杂度就会变成,。所以我们要想办法把只进行一层循环就能完成转置。

所以就要设置两个数值num[]和cpot[],num[]用于存储每列非零元素的个数,cpot[]用于存储每列第一个非零元素的初始位置。知道了每列非零元素的初始位置和非零元素的个数,而且列都是按大小来排的,所以转置时候一定的先遇到列数小的先放入,不用担心大小顺序会不同。于是就可以对三元组表进行一次遍历存储。

代码实现

void Transposition(TSMatrix *p,TSMatrix *q)
{q->nu=p->mu;q->mu=p->nu;q->tu=p->tu;//把行列数值对换,大小不变if(q->tu)    //如果三元组为空就不用{int i;int num[100],cpot[100];for(i=0; i<p->mu;i++)num[i]=0;       //初始化数组for(i=0;i<p->tu;i++)    //找出每列非零元个数,i=0存的第一列的++num[p->data[i].col - 1];cpot[0]=0;for(i=1;i<p->nu;i++)    //求每列第一个非零元素所在位置cpot[i]=cpot[i-1]+num[i-1];int a,b;for(i=0;i<p->tu;i++)    //进行转置{b=p->data[i].col-1;   a=cpot[b];    //找出每列所在位置 q->data[a].row = p->data[i].col;    //将其放入另外一个三元组表中q->data[a].col = p->data[i].row;q->data[a].e = p->data[i].e;++cpot[b];    //让其下次找到该列中的下一个非零元素}}}

        时间复杂度:O(nu+tu)

三元组顺序表又称有序的双下标法,它的特点是,非零元在表中按行序有序存储,因此便于进行依行顺序处理的矩阵运算。然而,若需按行号存取某一行的非零元,则需从头开始进行查找。

7.三元组表输出矩阵

void output(TSMatrix *p)
{printf("输出矩阵:\n");int i,j,k=0,a=0;for(i=1;i<=p->mu;i++){for(j=1;j<=p->nu;j++){if(p->data[k].row==i&&p->data[k].col==j){printf("%3d",p->data[k].e);k++;}elseprintf("%3d",a);}printf("\n");}
}

8.全部代码


#include<stdio.h>
#include<stdlib.h>
#define MAX 1000typedef struct
{int row,col,e;
}Triple;typedef struct
{Triple  data[MAX+1];int mu,nu,tu;     //矩阵的行数,列数和非零元个数
}TSMatrix;void input(TSMatrix *p,int m,int n)
{int i,j;int a[100][100];for( i=1;i<=m;i++)for(j=1;j<=n;j++){if(1+rand()%4>=1+rand()%19)a[i][j]=1+rand()%99;elsea[i][j]=0;}for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){printf("%4d",a[i][j]);}printf("\n");}p->tu=0;for(i=1;i<=m;i++)for(j=1;j<=n;j++){if(a[i][j]!=0){p->data[p->tu].row=i;  //行p->data[p->tu].col=j; //列p->data[p->tu].e=a[i][j]; //  数据++p->tu;}}}void printTriple(TSMatrix *p)
{printf("\n三元组:\n");for(int i=0;i<p->tu;i++){printf("%4d %4d %4d\n",p->data[i].row,p->data[i].col,p->data[i].e);}
}void sum(TSMatrix *A,TSMatrix *B,TSMatrix *C)
{C->mu=A->mu;C->nu=A->nu;C->tu=0;if(A->mu!=B->mu&&A->nu!=B->nu){printf("矩阵要大小相同才能相加!");return ;}int i=0,j=0;while(i<A->tu&&j<B->tu){if(A->data[i].row<B->data[j].row){C->data[C->tu].row=A->data[i].row;  //行C->data[C->tu].col=A->data[i].col; //列C->data[C->tu].e=A->data[i].e; //  数据C->tu++;i++;}else if(A->data[i].row==B->data[j].row){if(A->data[i].col<B->data[j].col){C->data[C->tu].row=A->data[i].row;   //行C->data[C->tu].col=A->data[i].col; //列C->data[C->tu].e=A->data[i].e; //  数据C->tu++;i++;           }else if(A->data[i].col>B->data[j].col){C->data[C->tu].row=B->data[j].row;   //行C->data[C->tu].col=B->data[j].col; //列C->data[C->tu].e=B->data[j].e; //  数据C->tu++;j++;}else{if(B->data[j].e+A->data[i].e!=0){C->data[C->tu].row=B->data[j].row;    //行C->data[C->tu].col=B->data[j].col; //列C->data[C->tu].e=B->data[j].e; //  数据C->tu++;}i++;j++;}}else{C->data[C->tu].row=B->data[j].row; //行C->data[C->tu].col=B->data[j].col; //列C->data[C->tu].e=B->data[j].e; //  数据C->tu++;j++;           }}while(i<A->tu){C->data[C->tu].row=A->data[i].row; //行C->data[C->tu].col=A->data[i].col; //列C->data[C->tu].e=A->data[i].e; //  数据C->tu++;i++;       }while(j<B->tu){C->data[C->tu].row=B->data[j].row;  //行C->data[C->tu].col=B->data[j].col; //列C->data[C->tu].e=B->data[j].e; //  数据C->tu++;j++;}}void Transposition(TSMatrix *p,TSMatrix *q)
{q->nu=p->mu;q->mu=p->nu;q->tu=p->tu;if(q->tu){int i;int num[100],cpot[100];for(i=0; i<p->mu;i++)num[i]=0;        //初始化数组for(i=0;i<p->tu;i++)++num[p->data[i].col - 1];cpot[0]=0;for(i=1;i<p->nu;i++)cpot[i]=cpot[i-1]+num[i-1];int a,b;for(i=0;i<p->tu;i++){b=p->data[i].col-1;a=cpot[b];q->data[a].row = p->data[i].col;q->data[a].col = p->data[i].row;q->data[a].e = p->data[i].e;++cpot[b];}}}void output(TSMatrix *p)
{printf("输出矩阵:\n");int i,j,k=0,a=0;for(i=1;i<=p->mu;i++){for(j=1;j<=p->nu;j++){if(p->data[k].row==i&&p->data[k].col==j){printf("%3d",p->data[k].e);k++;}elseprintf("%3d",a);}printf("\n");}
}int main()
{TSMatrix   A,B,C,T;printf("输入A矩阵的行列数:\n");scanf("%d%d",&A.mu,&A.nu);input(&A,A.mu,A.nu);printTriple(&A);printf("\n输入B矩阵的行列数:\n");scanf("%d%d",&B.mu,&B.nu);input(&B,B.mu,B.nu);printTriple(&B);sum(&A,&B,&C);printf("\nC的三元组:\n");printTriple(&C);output(&C);printf("\nA的转置:\n");Transposition(&A,&T);printTriple(&T);output(&T);getchar();getchar();return 0;
}

9.总结

三元组表在考研中,很多自主命题的大学喜欢考这个。在2021年安徽大学计算机专业考研中就出了一个15分的三元组快速转置的大题来考查学生(当年平均分在七八十分左右)。因为对于考生来说,三元组表很少有学生会认真思考,而且王道考研或者是其他考研资料,也很少讲三元组表方面的知识点。所以读者需要加强对三元组表的学习,尤其是快速转置。

数据结构:三元组的构建、相加和快速转置相关推荐

  1. SDUT 3347 数据结构实验之数组三:快速转置

    数据结构实验之数组三:快速转置 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 转置运算是一种最简单的矩阵运算,对于一个 ...

  2. 用三元组存储稀疏矩阵,实现其快速转置c语言代码,稀疏矩阵三元组表快速转置(C语言实现)...

    本来准备昨天下午写的,但是因为去参加360众测靶场的考核耽搁了,靶场的题目还是挺基础的. 继续学习吧. 使用黑色墨水在白纸上签名就像由像素点构成的稀疏矩阵.如图4所示. 图4手写体签名 [问题]请将以 ...

  3. 数据结构实验之数组三:快速转置

    Description 转置运算是一种最简单的矩阵运算,对于一个mn的矩阵M( 1 = < m < = 10000,1 = < n < = 10000 ),它的转置矩阵T是一个 ...

  4. 稀疏矩阵的三元组存储及快速转置

    问题描述 [问题描述] 实现稀疏矩阵的三元组表存储和快速转置运算. [输入形式] 输入一个整型的6阶稀疏矩阵. [输出形式] 输出稀疏矩阵的三元组表形式,使用快速转置方法进行转置运算,输出辅助数组nu ...

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

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

  6. c语言三元组稀疏矩阵的转置实验报告,稀疏矩阵快速转置 数据结构实验报告

    南昌航空大学实验报告 课程名称: 数据结构 实验名称: 实验五 稀疏矩阵的存储和快速转置 班 级: 学生姓名: 学号: 指导教师评定: 签 名: 题目:假设稀疏矩阵A采用三元组表表示,编写程序实现该矩 ...

  7. 矩阵三元组的快速转置

    1. 三元组矩阵的快速转置主要借助了两个外部数组,Num[]和Copt[],Num[]存放了转置之前的矩阵每一列中元素的个数.Copt[]矩阵存放了转置之后的三元组举证项应该存放的数据结构中的位置. ...

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

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

  9. 稀疏矩阵转置 java代码_三元组稀疏矩阵的快速转置

    小问题却整了这么久,能力有待加强,要强烈区分三元组的列数与元素总数, 不能将他俩写混了 #include #define MAXSIZE 1250 #define OK 1 #define ERROR ...

最新文章

  1. android eclipse 报error loading /system/media/audio/ xxx 错的解决办法。
  2. puppet 工作原理
  3. 云炬随笔20211012(1)
  4. java面试设计模式
  5. 网络协议文档阅读笔记-Introduction to DTLS(Datagram Transport Layer Security)
  6. WPF自定义控件 —— 布局
  7. linux CentOS7最小化安装环境静默安装Oracle11GR2数据库(修改配置文件)
  8. 短信开发的PDU格式
  9. Python:利用python代码编程实现将视频的avi格式转换为MP4格式
  10. java毕向东学习笔记——day09
  11. 2.7 汽车之家口碑爬虫
  12. HTML5期末大作业:旅游网站设计——北京旅游(1页) 北京旅游网页设计制作 简单静态HTML网页作品 我的旅游网页作业成品 学生旅游网站模板
  13. 扇贝单词里有计算机英语吗,扇贝单词英语版电脑版
  14. deepin v20桌面bug_“国产”Deepin桌面操作系统V20 正式版
  15. STM32系列 STM32F4xx SPI Flash-读写操作
  16. 记录一下自己写的小工具:shell 调度 SQL 批处理,递归查找调度路径
  17. Java求log2(N)
  18. 裸函数 __declspec(naked),C语言是怎么变成汇编的,用裸函数加汇编实现一个最简单的加法函数
  19. 【Electron-vue】创建桌面应用(12)- 修改electron窗口图标和桌面图标
  20. cad和mysql_在建筑行业,BIM 最终会取代 CAD 吗?

热门文章

  1. cpolar内网映射 远程ssh内网mac电脑
  2. 【HDU 1059】Dividing(多重背包)
  3. P2- 复信号 - 通讯原理
  4. Java实现对某一时刻GPS中圆轨道卫星的空间位置计算
  5. 【论文相关】SCI查询
  6. 一顿操作猛如虎,一看结果还是0,Rust能避免Go的BUG?
  7. 二十七、Java日常积累:\r \n回车和换行的区别
  8. 软件测试的基本概念(持续更新)
  9. Wireshark嗅探抓包工具
  10. 《SCDA:Adapting Object Detectors via Selective Cross-Domain Alignment》论文笔记