本来准备昨天下午写的,但是因为去参加360众测靶场的考核耽搁了,靶场的题目还是挺基础的。

继续学习吧。

使用黑色墨水在白纸上签名就像由像素点构成的稀疏矩阵。如图4所示。

图4手写体签名

【问题】请将以下稀疏点阵信息用三元组表进行存储,并:

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

(1)用稀疏矩阵快速转置法对该矩阵进行转置。转置前后的三元组表均以行序为主序。

(2)以阵列形式输出转置前后的稀疏矩阵,如图5所示。

图5  (a)转置前(b)转置后

先普及一下稀疏矩阵的概念:

简单理解稀疏矩阵就是元素大部分为零的矩阵,在实际生活中我们遇到的大型稀疏矩阵,如果按照常规的储存方法,就会造成大量空间的浪费,而且在访问和操作的时候也会造成大量时间上的浪费。三元组表就是为了解决这一问题而产生的解决方案之一。

稀疏矩阵由于其自身的稀疏特性,通过压缩可以大大节省稀疏矩阵的内存代价。具体操作是:将非零元素所在的行、列以及它的值构成一个三元组(i,j,v),然后再按某种规律存储这些三元组,这种方法可以节约存储空间,而这些三元组的集合,就是三元组表。

我们一步步来,将问题分解为一个个小模块,先将稀疏矩阵存储在三元组表中

因为C语言中没有三元组这种数据类型,所以我们先使用typedef定义三元组表:

typedef struct{

int i,j,val;

}NODE;

i,j,val分别表示三元组表的行,列以及非零元素的值。

这里的需要储存的稀疏矩阵也一起定义了

int nums[11][10]={

{0,1,1,1,1,1,1,1,0,0},

{1,0,0,0,0,0,0,0,1,0},

{1,0,0,0,0,0,0,0,1,0},

{0,0,0,0,0,0,0,1,0,0},

{0,0,0,0,0,0,1,0,0,0},

{0,0,0,0,0,1,0,0,0,0},

{0,0,0,0,1,0,0,0,0,0},

{0,0,0,1,0,0,0,0,0,0},

{0,0,1,0,0,0,0,0,0,0},

{0,1,0,0,0,0,0,0,0,0},

{1,1,1,1,1,1,1,1,1,1}

};

这里有一个问题是:

将稀疏矩阵存储到三元组表中时,需要记录稀疏矩阵的行列值吗?

答案是肯定的,如果不存储稀疏矩阵的行列值,当遇到稀疏矩阵最后一行全部是0的情况,由稀疏矩阵得到的三元组表,是无法还原成原来的稀疏矩阵的。

在上面的稀疏矩阵中,一共有28个非零元素,行值为11,列值为10,所以我们需要申请29个三元组的储存空间,多余的那一个储存空间用来存储稀疏矩阵的行,列值,以及稀疏矩阵中非零元素的个数

#define T 28

NODE matrix[T+1];

matrix[0].i=11;

matrix[0].j=10;

matrix[0].val=0;

用三元组表中第0个元素存储稀疏矩阵的基础信息

然后就到了将稀疏矩阵nums存储进三元组表的操作,遍历稀疏矩阵,当有元素为1的时候,将三元组表非零元素数量matrix[0].val++;然后依次将稀疏矩阵非零元素的信息存储进三元组表中

void init_matrix(NODE* matrix){

int i,j;

for(i=0;i

for(j=0;j

if(nums[i][j]==1){

matrix[0].val++;

matrix[matrix[0].val].i=i;

matrix[matrix[0].val].j=j;

matrix[matrix[0].val].val=nums[i][j];

}

}

}

}

存储了之后我们将三元组表输出还原成稀疏矩阵,看是否能正确还原

void put_matrix(NODE* matrix){

int i,j;

int count=1;

for(i=0;i

for(j=0;j

if(i==matrix[count].i&&j==matrix[count].j){

printf("%d",matrix[count].val);

count++;

}else{

printf("0");

}

}

printf("

");

}

}

程序运行的结果是

可以看到显示与原稀疏矩阵相同,说明存储入三元组表是正确的

接下来我们进行三元组表的快速转置,先贴一张上课时候的PPT

当然如果直接看PPT的话很有可能还是一头雾水,所以举一个形象的例子:

一个年级有四个班的同学,一班有20人,二班有30人,三班有40人,四班有50人,全年级的同学一起到电影院看电影,进了电影院之后,告诉我们要按照班级的顺序坐座位,座位只有一排,大家进电影院的时候都是跟自己熟悉的朋友一起,自然是乱序的,那我们应该怎么才能快速依次按照班级的顺序坐座位呢?

有一个办法是,大家随便坐座位,到了位置上之后,再进行班级顺序的比较,让一班的同学坐一班的位置,二班的同学坐二班的位置等等等,但是这样两两进行比较,效率未免过于低下。

另外的一个办法是,坐座位的时候,先把人群里面的一班同学筛选出来,依次放在一班同学的位置,然后再将人群里面的二班同学筛选出来,放在一班同学的后面位置,然后。。。

思考了之后,好像没有能够只筛选(遍历)一次人群就坐好座位的办法。

当然是!有的

所以就引入快速转置三元组表的办法,即如果我们提前知道每个班有多少人,在遍历人群的时候,只需要将其放在每个班开始的位置就行了。

如人群的开始班级排列是这样的 2,3,1,4,2,2,3.。。。。第一个同学是2班的,我们将其安排在第21号座位上(假设座位号是从1开始),因为我们知道前面会有20个一班的同学要坐座位,接着二号同学是三班的,安排在51号座位,三号同学是1班的,安排在1号座位,四号同学是四班的,安排在91号座位,五号同学!又是二班的,但是原来二班的同学已经坐了21号,所以我们理所当然地坐在22号座位,后面的也是这样,只需要遍历一次原人群,就能将同学们按照顺序坐在相应的位置上了。

但是在上面的描述中,我们需要知道每个班有多少人,以及每个班的第一个位置是在哪里(比如最开始二班同学的第一个位置是21号座位,有同学坐了21号座位之后,第一个位置自然就后移成22号座位了,等待下一个同学来坐,坐了之后再继续后移),所以需要两个辅助数组来存储这两个信息

num数组用来存储每个班中的人数,cpot数组用来存储每个班的第一个位置。

在三元组表快速转置中,num[i]表示原三元组表中第i列中非零元的个数,cpot[i]表示原三元组表中第i列中第一个非零元素的在新的三元组表中的位置(cpot这一段可能有点绕,再解释一下,因为在题目中,我们需要转置之后的三元组表按照行主序排列,由于是转置之后的,说明我们的顺序在转置之前,是按照列序在新的三元组表中放置,即如果新的三元组表中有(2,1),(1,2),那么(1,2)会在(2,1)的下面,因为2>1,找到其在三元组表中对应的位置后,再进行行列转置)

接下来将新三元组表中第0元素设置好

new_matrix[0].i=matrix[0].j;

new_matrix[0].j=matrix[0].i;

new_matrix[0].val=matrix[0].val;

然后初始化num数组和cpot数组,这里需要提到的是两个PPT里面也显示了的关系,再贴一次:

cpot[i]表示原三元组表中第i列中第一个非零元素在新的三元组表中的位置,可以理解为同学们去看电影的时候,每个班在电影院座位上的最开始那个座位,比如二班的同学最开始是21,三班的同学是51,但是有一个显而易见的事实是(别告诉我你没看出来:-)当然没看出来也没事),一班的同学在座位中最开始的座位是1,这个是不需要遍历人群,也不需要由班级人数可以确定的,而其他每个班开始的位置,是上一个班的开始位置+上一个班的人数,如21=1+20,1是一班开始的座位,20是1班的人数,三班的同学由二班的位置又可以得到51=21+30,依次类推初始化cpot

for(i=0;i

num[i]=0;

}

for(i=1;i<=matrix[0].val;i++){

num[matrix[i].j]++;

}

cpot[0]=1;

for(i=1;i

cpot[i]=cpot[i-1]+num[i-1];

}

最后就是最关键的转置的时候了,当然经过前面这么多的铺垫,最后这一步已经显得很简单了,和大家去看电影这个例子一样,按照步骤放位置就行了。

使用tmp变量存储该元素属于哪一列(哪一个班级),first变量存储其列在新的三元组表中存储的位置(该班级同学坐的第一个位置),然后将原三元组表中的数据转置之后放进去就行了,最后让这个列在新的三元组表中存储位置后移一位(后来的该班同学只好坐在这个同学后面啦),代码已经不是很重要了

for(i=1;i<=matrix[0].val;i++){

tmp=matrix[i].j;

first=cpot[tmp];

new_matrix[first].i=matrix[i].j;

new_matrix[first].j=matrix[i].i;

new_matrix[first].val=matrix[i].val;

cpot[tmp]++;

}

分析完了之后是不是感觉也没那么难了呢,其实关键的代码只有那么几处,慢慢分析是可以缕清思路的。

转置后输出结果为:

完整代码如下:

#include

#include

#define MAX 111

int nums[11][10]={

{0,1,1,1,1,1,1,1,0,0},

{1,0,0,0,0,0,0,0,1,0},

{1,0,0,0,0,0,0,0,1,0},

{0,0,0,0,0,0,0,1,0,0},

{0,0,0,0,0,0,1,0,0,0},

{0,0,0,0,0,1,0,0,0,0},

{0,0,0,0,1,0,0,0,0,0},

{0,0,0,1,0,0,0,0,0,0},

{0,0,1,0,0,0,0,0,0,0},

{0,1,0,0,0,0,0,0,0,0},

{1,1,1,1,1,1,1,1,1,1}

};

typedef struct{

int i,j,val;

}NODE;

#define T 28

void put_matrix(NODE* matrix){

int i,j;

int count=1;

for(i=0;i

for(j=0;j

if(i==matrix[count].i&&j==matrix[count].j){

printf("%d",matrix[count].val);

count++;

}else{

printf("0");

}

}

printf("

");

}

}

void init_matrix(NODE* matrix){

int i,j;

for(i=0;i

for(j=0;j

if(nums[i][j]==1){

matrix[0].val++;

matrix[matrix[0].val].i=i;

matrix[matrix[0].val].j=j;

matrix[matrix[0].val].val=nums[i][j];

}

}

}

}

void put_nums(){

int i,j;

for(i=0;i<11;i++){

for(j=0;j<10;j++){

printf("%d",nums[i][j]);

}

printf("

");

}

}

void reverse_matrix(NODE* matrix,NODE* new_matrix){

int num[matrix[0].j],cpot[matrix[0].j];

int tmp,first,i;

new_matrix[0].i=matrix[0].j;

new_matrix[0].j=matrix[0].i;

new_matrix[0].val=matrix[0].val;

for(i=0;i

num[i]=0;

}

for(i=1;i<=matrix[0].val;i++){

num[matrix[i].j]++;

}

cpot[0]=1;

for(i=1;i

cpot[i]=cpot[i-1]+num[i-1];

}

//转置存储

for(i=1;i<=matrix[0].val;i++){

tmp=matrix[i].j;

first=cpot[tmp];

new_matrix[first].i=matrix[i].j;

new_matrix[first].j=matrix[i].i;

new_matrix[first].val=matrix[i].val;

cpot[tmp]++;

}

}

int main(){

int i,j;

NODE matrix[T+1],new_matrix[T+1];

matrix[0].i=11;

matrix[0].j=10;

matrix[0].val=0;

printf("储存入三元组表前:

");

put_nums();

printf("初始化三元组表...");

init_matrix(matrix);

printf("

使用三元组表按行主序进行储存后:

");

put_matrix(matrix);

printf("正在转置...");

reverse_matrix(matrix,new_matrix);

printf("

转置后的结果为:

");

put_matrix(new_matrix);

return 0;

}

以上

matrix[

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

  1. 用三元组存储稀疏矩阵及其快速转置

    用三元组存储稀疏矩阵及其快速转置 稀疏矩阵的三元组存储方式 快速转置算法 代码 稀疏矩阵的三元组存储方式 稀疏矩阵可以用一个三元组数组表示,数组每个元素是一个三元组,三元组形式为 (矩阵行号,矩阵列号 ...

  2. 用三元组存储稀疏矩阵并实现转置

    基本概念 在学习线性代数的时候,经常用到矩阵.在C语言中,表示矩阵的最直观形式就是二维数组.然而在实际应用中,很多高阶矩阵中的非零元素非常少,这个时候如果继续使用二维数组存储,那么就会浪费很多存储空间 ...

  3. 数据结构 实验14(1-2班):(深入理解索引存储结构)三元组存储的稀疏矩阵建立行列索引并求鞍点

    目录 前言: 需求分析: 难点分析: 代码和思路详解: 三元组表的头文件: 建立索引思路: 什么是三元组表的索引: 结合题意实现索引表: 建立索引表的代码实现: 索引表的结构体定义: 索引表的创建思路 ...

  4. 稀疏矩阵的三元组存储方法c语言,数据结构C语言版 稀疏矩阵的三元组顺序表存储表示和实现...

    陈独秀的秘密 数据结构C语言版 稀疏矩阵的三元组顺序表存储表示和实现 P98 编译环境:Dev-C++ 4.9.9.2 日期:2011年2月8日 */ typedef int ElemType; // ...

  5. 特殊矩阵的压缩存储(对称矩阵,三角矩阵,对角矩阵,稀疏矩阵的顺序,链序存储,十字链表的建立)

    特殊矩阵的压缩存储 压缩存储的定义: 若多个数据元素的值都相同,则只分配一个元素值的存储空间,且 零元素不占存储空间. 能够压缩的一些矩阵: 一些特殊矩阵,如:对称矩阵,对角矩阵,三角矩阵,稀疏矩阵等 ...

  6. 三元组转化矩阵 java_矩阵转置算法及代码实现(三元组顺序表)

    矩阵的转置实际上就是将数据元素的行标和列标互换,即 T(i,j) = M(j,i) .例如: 相应地,三元组表转变为: 图2 三元组表 矩阵的转置,经历了三个步骤: 矩阵的行数 n 和列数 m 的值交 ...

  7. 5.3矩阵乘积(三元组存储结构)

    行逻辑链表的顺序表 为了便于随机存取任意一行的非零元,则需要知道每一行的第一个非零元在三元组表中的位置.为此,可将上节快速转置矩阵中的算法创建的,指示"行"信息的辅助数组cpot固 ...

  8. 稀疏矩阵 c语言,C语言数据结构 稀疏矩阵

    <C语言数据结构 稀疏矩阵>由会员分享,可在线阅读,更多相关<C语言数据结构 稀疏矩阵(4页珍藏版)>请在人人文库网上搜索. 1.实验十 稀疏矩阵#include #defin ...

  9. oracle查询不走索引全表扫描,使用索引快速全扫描(Index FFS)避免全表扫描的若干场景-Oracle...

    使用索引快速全扫描(Index FFS)避免全表扫描的若干场景 什么使用使用Index FFS比FTS好? Oracle 8的Concept手册中介绍: 1. 索引必须包含所有查询中参考到的列. 2. ...

最新文章

  1. [高级软件工程教学]结队第1次作业成绩公布
  2. scala-wordcount
  3. python 用户的画像可视化呈现技术_一人一车一面:解读汽车大数据用户画像背后的AI技术...
  4. Debian6 / 7 Web服务器环境搭建LNMP一键安装包 | 问题汇总与解答
  5. 计蒜客-----泥塑课(set)
  6. 计算机四级网络工程师等级考试题库软件---百度云分享
  7. 社区发现算法——Louvain 算法
  8. mac打开注册机显示“您没有权限来打开应用程序
  9. 有没有大讨论,联想都要面对 “第四道槛”
  10. python批量制作ppt_python批量将文件夹内所有PPT转化为PPTX
  11. 智能的未来关键在于发现新的逻辑体系
  12. halcon中如何生成椭圆_Halcon中关于角度计算和测量拟合的算子详解
  13. 解决maven 引用JDK内部类编译错误 程序包:com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler不存在...
  14. uIP TCP/IP协议栈
  15. AI-Info-Micron-Insight:案例分析:美光使用数据和人工智能来发现、倾听和感觉
  16. 嵌入式系统裸机程序开发与调试
  17. Java性能优化怎么做好
  18. 优化算法(一):牛顿法与拟牛顿法
  19. Windows 98 入门介绍大全(一)(转)
  20. [兴趣-画画] 基础 1

热门文章

  1. 形态学 - 提取连通分量
  2. 2020年升降机司机考试软件及升降机司机操作证考试
  3. 建筑升降机司机证在哪里怎么报名考试报名条件是什么
  4. php点击事件下一页,点击上一页下一页信息没有更新
  5. qt 控件坐标系_Qt学习之路(28): 坐标变换
  6. objective-c过滤HTML标签
  7. Mysql-Explain用法详解
  8. Bigpipe学习【转】
  9. 异步电机无感MRAS-cc(三.推导及仿真)
  10. 函授大专和成人大专哪个含金量更高