稀疏数组如何帮助我们节省内存,提升性能
本文由葡萄城技术团队发布。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。
什么是稀疏矩阵
稀疏矩阵是指矩阵中大部分元素为零的矩阵。在实际应用中,很多矩阵都是稀疏的,比如网络图、文本数据等。由于矩阵中存在大量的零元素,因此稀疏矩阵的存储和计算都具有一定的特殊性。
一般来说,在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。下面的矩阵就是一个典型的稀疏矩阵:
优化稀疏矩阵数据存储的方法
1.直接存储为二维矩阵
使用二维矩阵作为电子表格的存储方法具有简单直接的优点,可以避免频繁地创建或删除内存段。然而,需要指出的是,这种方式在存储值时可能会有一些不太高效的方面,因为它会占用大量的存储空间来保存没有实际内容的单元格。
在实际应用中通常使用三元组表示稀疏矩阵:
三元组的表示方法是:对于一个 m×n 的稀疏矩阵 A,我们只存储矩阵中非零元素的信息,具体来说,将每个非零元素的行下标、列下标和值存储下来,得到一个三元组(i,j,Ai,j),其中 i 是行下标,j 是列下标,Ai,j 是 A 中对应位置的值。
以前面举的稀疏矩阵为例,其三元组表示如下:
(1, 4, 6) (2, 2, 5) (3, 3, 4)
直接存储为二维矩阵的复杂度:
- 占用空间:O(N2) 。
- 插入数据:需要破坏矩阵。
- 删除数据:需要破坏矩阵。
- 搜索数据:O(N2)。
- 访问数据:O(1)。
N是假设行和列具有相同长度并形成正方形矩阵的行/列数。
2.通过键值对(Map, Dictionary)优化
通过键值对(Map, Dictionary)来优化,主要是利用哈希表的特性来快速查找元素。具体来说,可以将需要查找的元素作为键,将存储这些元素的数据结构作为值,然后将它们存储在一个哈希表中。这样,当需要查找某个元素时,只需要使用该元素作为键,通过哈希表的查找操作即可快速找到对应的值。
在实际应用中,常见的情况包括:
- 缓存数据:在需要频繁访问数据的场景中,通过建立一个缓存,将数据存储在一个键值对的数据结构中,可以显著提高数据的访问效率。
- 字符串处理:在需要对字符串进行匹配、查找等操作的场景中,可以将字符串作为键,将相应的处理结果作为值,存储在一个键值对的数据结构中,可以大幅提高字符串处理的效率。
- 数据库操作:在需要对数据库进行访问的场景中,可以使用键值对数据结构来存储查询结果,避免重复执行查询操作,减轻数据库的负载。
在下图中,将单元格位置和对应的单元格值以键值对的形式进行了存储。
通过键值对(Map, Dictionary)优化稀疏数组的复杂度:
- 空间:O(N)。
- 插入:O(1)。
- 删除:O(1)。
- 搜索:O(N)。
- 访问:O(1)。
N为所记录的条目数。
3.通过数组存储方式优化
在稀疏矩阵中,我们可以使用三个不同的数组来存储行索引、列偏移、和其中的值,而不是直接在二维矩阵中存储值。
存储的三个数组:
- 值 =>单元格中的值。
- 行索引=>单元格的行索引。
- 列偏移=>这里每个索引都代表列,并且该数组将行开始的索引值存储在 Row 数组中。
下图为将稀疏数组转化为数组的形式:
稀疏矩阵具体的插入,删除,搜索,访问的代码:
import java.util.HashMap; import java.util.Map; class SparseMatrix { private int rows; private int cols; private Map<String, Integer> matrix; public SparseMatrix(int rows, int cols) { this.rows = rows; this.cols = cols; this.matrix = new HashMap<>(); } public void insert(int row, int col, int value) { if (row < 0 || row >= rows || col < 0 || col >= cols) { throw new IndexOutOfBoundsException("Invalid matrix index"); } if (value != 0) { String key = row + "," + col; matrix.put(key, value); } } public void delete(int row, int col) { String key = row + "," + col; matrix.remove(key); } public int search(int row, int col) { String key = row + "," + col; return matrix.getOrDefault(key, 0); } public int access(int row, int col) { if (row < 0 || row >= rows || col < 0 || col >= cols) { throw new IndexOutOfBoundsException("Invalid matrix index"); } String key = row + "," + col; return matrix.getOrDefault(key, 0); } }
在上述代码中,定义了一个 SparseMatrix 类来表示稀疏矩阵。在构造函数中,我们传入矩阵的行数和列数,并创建了一个 HashMap 对象 matrix 来存储非零元素。insert 方法用于向矩阵中插入元素,如果插入的值不为零,则将其加入 matrix 中,其中键为字符串形式的 row,col。delete 方法用于删除指定位置的元素,通过 remove 方法从 matrix 中移除对应的键值对。search 方法用于搜索指定位置的元素,通过调用 getOrDefault 方法从 matrix 中获取对应的值,如果不存在则返回默认值 0。access 方法用于访问指定位置的元素,如果超出矩阵边界则抛出异常,通过调用 getOrDefault 方法从 matrix 中获取对应的值。
通过稀疏矩阵存储方式优化的复杂度:
- 空间:O(N)。
- 插入:O(N)。
- 删除:O(N)。
- 搜索:O(N)。
- 访问:O(1)。
总结
相较于传统的数组存储或键值对存储,稀疏矩阵存储采用一种基于行索引的数据字典存储方法,这种方法在处理松散布局的表格数据时表现出色。与其他存储方式不同,稀疏矩阵只存储非空数据,无需额外开辟内存空间来存储空数据。这种特殊存储策略使得数据片段化变得容易,可以随时框取整个数据层中的一片数据进行序列化或反序列化。如果在项目开发中需要存储类似结构的数据,使用稀疏矩阵存储方式能够显著提升性能,无论从时间还是空间上都有很大的优势,葡萄城公司的纯前端表格控件——SpreadJS正是借助此功能实现了高性能渲染能力(100 毫秒内加载 10 万行数据)。
扩展链接:

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
KubeSphere 社区双周报 | KubeSphere 3.4.1 发布 | 2023.10.27-11.09
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为:2023.10.27-2023.11.09。 贡献者名单 新晋 KubeSphere Contributor 两周内共有 8 位新晋 KubeSphere Contributor,感谢各位对 KubeSphere 社区的贡献! GitHub ID 证书 Ganbingkun 下载证书 MisterMX 下载证书 Shimada666 下载证书 donniean 下载证书 guerzon 下载证书 liuxu623 下载证书 nyuxiao 下载证书 samt42 下载证书 新晋 KubeSphere Talented Speaker 在上周六(11.4)KubeSphere 社区联合 SOFAStack 社区及 KubeBlocks 社区共同组织了成都站 Meetup,在本次 Meetup 中共诞生了五位新的 KubeSphere Talented Spe...
- 下一篇
我们真的需要这么多 RPC 框架吗?
10 月 18 日,腾讯开源了 RPC 开发框架——tRPC,号称具有“多语言、高性能”的特点,首批开源支持 Go / Cpp 两种编程语言。 众所周知,现有的开源 RPC 框架已经很多了, gRPC、Thrift、Dubbo、bRPC,难道就没有一个能腾讯满足需求吗,腾讯是不是在重复造轮子?我们真的需要这么多 RPC 框架吗? 为此,开源中国对腾讯tRPC团队进行了采访,来解答网友心中的部分疑惑。 一、有网友认为现有的开源 RPC 框架已经很多了,腾讯搞tRPC 是在重复造轮子。您怎么看待这种观点? 存量的框架的确够多了,但对腾讯来说,多一套框架不能只是多了一套,核心是让存量归一。 以前在腾讯,都是由业务自己选择RPC框架,造成在用的框架种类繁多,有开源的,有自研的,达数十种。它们使用的通信协议不一样,使用的名字服务不一样,造成服务之间互通不顺畅,阻碍了业务的发展。同时,众多的RPC框架维护和使用成本也很高,急需收敛存量框架。是选择一个存量框架还是重新开发一个新的框架去做收敛,我们在开发tRPC之前,也深度思考了这个问题,并在内部进行了充分的讨论,最终决定采用自研tRPC。因为腾讯的...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Hadoop3单机部署,实现最简伪集群
- CentOS6,7,8上安装Nginx,支持https2.0的开启