5.3矩阵的压缩存储(稀疏矩阵转置和快速转置)
在矩阵中有许多值相同的元素或者是零元素。有时为了节省存储空间,可以对这类矩阵进行压缩存储。所谓的压缩存储是指:为多个值相同的元值分配一个存储空间;对零元不分配空间。
5.32稀疏矩阵
在m*n的矩阵中,有t个元素不为零。零α=t/m*n,称 α为矩阵的稀疏因子。通常认为α<=0.05时称为稀疏矩阵。
对于稀疏矩阵的非零元我们有下面这个表示:
如:(,(1,2,12),(1,3,9),(3,1,-3),(3,6,14),(4,3,24),(5,2,18),(6,1,15),(6,4,-7))
如下图所示:
下面我们来看下三元组的结构体:
下面是书中代码(严蔚敏版的数据结构)
#define MAXSIZE 12500 //非零元素个数的最大值为12500
typedef struct{int i, j; //该非零元的行下标和列下标ElemType e;
}Triple;typedef struct{Triple data[MAXSIZE + 1]; //非零元三元组表,data[0]未用int mu, nu, tu; //矩阵的行数、列数和非零元个数
}TSMatrix;
分析下:
这里的思路和我们在链表上看到的有相似之处,结点变成了非零元素,线性表编程了非零元三元组的表。但多出了矩阵的行数,列数和非零元个数
学过线性代数的都知道,转置运算是一种最简单的矩阵运算。
对应一个m*n的矩阵M它的转置矩阵是T,如下图所示:
P·S:所谓的置换就是行和列进行交换,也就是关于主对角线对称(矩阵左上角到右下角的线称为主对角线)
而在程序里面,他将会是下面这张图这样:
这里的i对应行,j对应列,v表示值。
从分析a和b之间的差异可见只要做到:
1.将矩阵的行列值相互转换。
2.将每个三元组中的i和j交换。
3.重排三元组之间的次序便可实现矩阵的转置。
下面是书中给我们提供的伪代码:
Status TransposeSMatrix(TSMatrix M, TSMatrix &T)
{ // 采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵Tint p, q, col;T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;if (T.tu) {q = 1;for (col = 1; col <= M.nu; ++col)for (p = 1; p <= M.tu; ++p)if (M.data[p].j == col){T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i;T.data[q].e = M.data[p].e; ++q;}}return Ok;
} // TransposeSMatrix
下面来分析下:
col表示列,从M矩阵的第一列开始。比如col=1时,他先检索M的第一列,把非零元中第一列的换成T中的第一行,就这个思路。
下面是矩阵的快速转置方法:
原理是:如果能预先确定矩阵M中每一列(即T中每一行)的第一个非零元在b.data中(上面那图是b.data)恰当位置。那么在对a.data中的三元组一次做转置时,便可直接放到b.data中恰当的位置上去。
设两个向量:num和cpot
num[col]表示矩阵M中第col列中的非零元素个数。
cpot[col]指M中第col列的第一个非零元在b.data中的恰当位置。
有下面两个公式:
cpot[1]=1;
cpot[col]=copt[col-1]+num[col-1] 2<=col<=a.nu
图如下:
下面来分析下这个表:
cpot[1]=1.
cpot[2]=num[1]+cpot[1]=1+2=3
cpot[3]=num[2]+cpot[2]=2+3=5
cpot[4]=num[3]+cpot[3]=2+5=7
cpot[5]=num[4]+cpot[4]=1+7=8
cpot[6]=num[5]+cpot[5]=0+8=8
cpot[7]=num[6]+cpot[6]=1+8=9
这个表就是这么填的,但是在代码里面就不一样了。我这里先提一下,代码里面有覆盖和范围这种概念,这是什么意思,意思就是,大家看cpot[5]和cpot[6]都是8,那么在最后,他只会保留cpot[6],而cpot[7]他这里是9,但本身就只有8个元素,哪来第九个呢?所以这个cpot[9]在程序里面是没有用的。
下面是书中代码:
Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T)
{ // 采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵Tint col, t, p, q;int num[20], cpot[20];T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;if (T.tu) {for (col = 1; col <= M.nu; ++col) //对列数进行初始化num[col] = 0;for (t = 1; t <= M.tu; ++t) // 求 M 中每一列所含非零元的个数++num[M.data[t].j];cpot[1] = 1;// 求 M 中每一列的第一个非零元在 b.data 中的序号for (col = 2; col <= M.nu; ++col) cpot[col] = cpot[col - 1] + num[col - 1];for (p = 1; p <= M.tu; ++p) {col = M.data[p].j; q = cpot[col];T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i;T.data[q].e = M.data[p].e; ++cpot[col];} // for} // ifreturn OK;
} // FastTransposeSMatrix
分析如下:
这个程序的关键就是他只用了一个for循环,而上面那个程序用了两个for循环,这使得时间复杂度降低了。这个for(p=1;p<M.tu;++p).这个就是我刚刚在上表说的那个意思。这里有个++cpot[col]这是个关键
现在来解释下++cpot[col]:
我们可以看到上表中cpot[col]只有1,3,5,7,8而2,4,5没有,所以用了这个++cpot[col]后他就把每一列的第一个元素移到了第二个。
如果还有同学不懂,下面我给出全部的代码。
不懂的同学单步调试下。
#include <stdio.h>
#include <windows.h>
#define MAXSIZE 1250 #define OK 1
#define ERROR 0
#define TRUE 1
#define FLASE 0 typedef int Status;
typedef int ElemType;typedef struct{int i, j; //该非零元的行下标和列下标 ElemType e; //非零元对应的值
}Triple;typedef struct{Triple data[MAXSIZE + 1]; //非零元三元组表,data[0]未用 int mu, nu, tu; //矩阵的行数,列数,非零元个数
}TSMatrix;Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T) //快速转置
{ //采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵T T.mu = M.nu;T.nu = M.mu;T.tu = M.tu;if (T.tu){int col;int num[100], cpot[100];for (col = 1; col <= M.nu; ++col)num[col] = 0; //num数组的初始化 for (int t = 1; t <= M.tu; ++t)++num[M.data[t].j]; //求M中每一列含有的非零元个数 cpot[1] = 1;for (col = 2; col <= M.nu; ++col)cpot[col] = cpot[col - 1] + num[col - 1]; //求cpot向量 int q;for (int p = 1; p <= M.tu; ++p){col = M.data[p].j;q = cpot[col];T.data[q].i = M.data[p].j;T.data[q].j = M.data[p].i;T.data[q].e = M.data[p].e;++cpot[col];}//for }//if return OK;
}//FastTransposeSMatrix Status main()
{TSMatrix M;TSMatrix T;printf("请输入原矩阵:\n");printf("行数、列数: ");scanf_s("%d%d", &M.mu, &M.nu);printf("元素总数: ");scanf_s("%d", &M.tu);printf("输入各个对应压缩值:\n");for (int i = 1; i <= M.tu; ++i)scanf_s("%d%d%d", &M.data[i].i, &M.data[i].j, &M.data[i].e);FastTransposeSMatrix(M, T);printf("转置后行数、列数、元素总数非别为:\n%d %d %d\n\n", T.mu, T.nu, T.tu);printf("值为:\n");for (int t = 1; t <= T.tu; ++t)printf("%d %d %d\n", T.data[t].i, T.data[t].j, T.data[t].e);system("pause");return OK;
}
运行结果如下:
和下面这图是不是一模一样
5.3矩阵的压缩存储(稀疏矩阵转置和快速转置)相关推荐
- 用三元组存储稀疏矩阵,实现其快速转置c语言代码,稀疏矩阵三元组表快速转置(C语言实现)...
本来准备昨天下午写的,但是因为去参加360众测靶场的考核耽搁了,靶场的题目还是挺基础的. 继续学习吧. 使用黑色墨水在白纸上签名就像由像素点构成的稀疏矩阵.如图4所示. 图4手写体签名 [问题]请将以 ...
- 矩阵-----对称矩阵及其压缩存储稀疏矩阵
什么是对称矩阵(SymmetricMatrix)? 对称对称-------看 设一个N*N的方阵A,A中任意元素Aij,当且仅当Aij == Aji(0 <= i <= N-1 & ...
- 矩阵的压缩存储(随机稀疏矩阵的建立和输出)
实际应用中会有很多利用高阶矩阵的问题,有的高阶矩阵已达到几十万阶,几千亿个元素.然而,多数的高阶矩阵中包含了大量的数值为零的元素,需要对这类矩阵进行压缩存储.因为合理的压缩存储不仅能有效地节省存储空间 ...
- 特殊矩阵的压缩存储(对称矩阵,三角矩阵,对角矩阵,稀疏矩阵的顺序,链序存储,十字链表的建立)
特殊矩阵的压缩存储 压缩存储的定义: 若多个数据元素的值都相同,则只分配一个元素值的存储空间,且 零元素不占存储空间. 能够压缩的一些矩阵: 一些特殊矩阵,如:对称矩阵,对角矩阵,三角矩阵,稀疏矩阵等 ...
- 特殊矩阵的压缩存储(详细版 通俗易懂 含c语言稀疏矩阵十字链表代码 )
前言 此文章是本人第一篇博客,目的在于巩固过去所学的知识,同时可能会给大家带来一丝丝帮助,但由于没有经验加上本人能力极其有限,文章中可能存在不足之处,还请读者能够指正(`・ω・´). 这篇文章首先会介 ...
- 数据结构笔记(十七)--矩阵的压缩存储
矩阵的压缩存储 一.矩阵的分类 1.特殊矩阵:其矩阵值在在矩阵中分布有规律 2.稀疏矩阵:矩阵的非零值在矩阵中占比小于0.05的矩阵,即零值占比在95%以上 3.一般矩阵:不属于上面的两种矩阵 二.矩 ...
- 数据结构C语言实现-矩阵的压缩存储
一.矩阵的压缩存储: 在编写程序时往往都是二维数组表示矩阵,然而在数值分析中经常出现一些阶数很高的的矩阵同时在距震中有很多值相同的元素,或者是零元素,为了节省空间,可以对这类矩阵进行压缩存储,所谓的压 ...
- 十字链表 java_十字链表法,十字链表压缩存储稀疏矩阵详解
对于压缩存储稀疏矩阵,无论是使用三元组顺序表,还是使用行逻辑链接的顺序表,归根结底是使用数组存储稀疏矩阵.介于数组 "不利于插入和删除数据" 的特点,以上两种压缩存储方式都不适合解 ...
- 9.特殊矩阵的压缩存储
压缩存储:指多个值相同的元素只分配一个存储空间, 对零元素不分配存储空间. 特殊矩阵:指具有许多相同矩阵元素或零元素,并且这些相同矩阵元素或零元素的 分布有一定规律性的矩阵. 特殊矩阵的压缩存储:找出 ...
最新文章
- 和12岁小同志搞创客开发:手撕代码,做一款火焰报警器
- 【Zookeeper】源码分析之Leader选举(一)
- JS通过正则限制 input 输入框只能输入整数、小数(金额或者现金) 两位小数
- LSM树——放弃读能力换取写能力,将多次修改放在内存中形成有序树再统一写入磁盘...
- [教程] [承風雅傳HSU]用ES4封裝Win7---ES4 Win7封裝教程(未完待續)
- 1、MySQL为什么需要事务?
- python学习笔记二— 循环
- 内推学弟进了腾讯,看看他的标杆简历!
- ndarray.ravel([order]) 和 ndarray.flatten([order])
- 没有基础怎么学习Web前端?相关学习路线又是什么?
- Leetcode每日一题:52.N-Queens II(N皇后Ⅱ)
- python使用函数输出指定范围内fibonacci数的个数_第6章函数-4 使用函数输出指定范围内Fibonacci数的个数...
- 有道单词本添加js实现自动阅读单词
- 工程项目全过程,工程项目建设分为几个阶段?
- 大数据平台开发公司有哪些?
- 51单片机间接寻址C语言,51单片机的寻址方式
- 常用软件的 Linux 版本
- Nacos本地进行了远程配置而远程未配置相关信息而导致应用报内存泄漏问题的异常
- python条件语句作用_Python 条件语句
- 【latex入门】基本语法|常见报错