C++ 为行/列操作设计的稀疏矩阵存储格式?

C++ 为行/列操作设计的稀疏矩阵存储格式?,c++,matrix,C++,Matrix,我正在使用一个需要在稀疏矩阵中访问和存储数据的程序。大约40-60%的矩阵为非零矩阵,尺寸为14K到22K的正方形元素 这是我的问题-我将执行大量的行和列操作。主要是添加、删除和交换。我已经研究了大多数现有的众所周知的稀疏矩阵格式(CRS、CCS、COO、块格式等),它们中的大多数似乎不太接受这些类型的操作。在开始添加和删除整行或整列时,必须将所有元素更新到被操纵行/列的任一侧,如果可能的话,我希望尽量避免这样做(我突然想到,您可能可以以这样一种方式管理元素,即它们在矩阵中的坐标实际上存储为指向

我正在使用一个需要在稀疏矩阵中访问和存储数据的程序。大约40-60%的矩阵为非零矩阵,尺寸为14K到22K的正方形元素

这是我的问题-我将执行大量的行和列操作。主要是添加、删除和交换。我已经研究了大多数现有的众所周知的稀疏矩阵格式(CRS、CCS、COO、块格式等),它们中的大多数似乎不太接受这些类型的操作。在开始添加和删除整行或整列时,必须将所有元素更新到被操纵行/列的任一侧,如果可能的话,我希望尽量避免这样做(我突然想到,您可能可以以这样一种方式管理元素,即它们在矩阵中的坐标实际上存储为指向公共行或列索引的一对指针,并通过简单地增加或减少该值来避免手动更新数千个元素)


是否存在类似的情况?

我会考虑一个间接层,作为交换、插入和删除行和列的有效机制。

这类似于现代操作系统中虚拟内存的管理方式。这只是一个简短的旁白:物理RAM地址由CPU映射到线性寻址空间。MMU在主机O/s的帮助下,将实际物理RAM地址映射到每个进程的虚拟地址空间。指针使用的地址,每个进程中的其他对象不是真实的RAM地址,它们是虚拟的,并由硬件MMU单元转换为实际的物理RAM地址。这就是为什么当系统空间不足时,主机操作系统可以将空闲进程调出到交换文件或分区中,然后重新加载到某个完整的内存中y物理RAM的不同区域,进程甚至不知道发生了什么

无论如何,回到主题上来,这将是一个类似的方法

考虑一个普通的、花园式的二维
std::map

std::map<size_t, std::map<size_t, value_t>>
std::map
第一个映射的维度或键是行,它为您提供了第二个映射,其维度/键是列,最后包含您的值

这很简单。这里没有什么惊天动地的。但正如您所理解的:移动、交换和插入行和列变得相当困难

好的,让我们介绍一下您自己的个性化MMU:您的地图管理单元。它的工作原理与硬件MMU非常相似:

std::map<size_t, size_t> rows;
std::map<size_t, size_t> columns;
std::映射行;
std::映射列;
因此,在您的示例中,要查找虚拟行
R
,列
C
,请执行以下操作:

1)
行[R]
提供“物理”行号

2)
columns[C]
提供“物理”列编号

3) 现在,获取“物理”行和列编号,然后转到二维
std::map
,并查找给定物理行和列的值

那么,我们得到了什么?现在,移动整行或整列需要对地图管理单元进行简单的更新。从
映射中删除一个值,然后使用另一个键(新的“逻辑”行或列)将其放回。“物理”二维地图中的值保持不变

就这样。移动、交换或插入行成为mmu对象上的一个简单操作

还有两个其他细节需要注意:

A) 跟踪哪些物理行和列不是未使用的,并且可以在添加时分配给新的逻辑行和列

B) 根据您的用例,可能还需要将物理行和列映射回虚拟行和列编号


这两个都是相当琐碎、简单的任务,这可能是你的家庭作业。

因为你有那么多的操作,而且你使用的是稀疏矩阵,你不应该考虑使用一组链表来代替吗?您可以节省浪费的空间,并且您的操作应该更容易(特别是交换)您是否考虑过
std::unordered\u map
?一个典型的矩阵有多少行,多少列?“尺寸在14K到22K的任何地方都是正方形”-这是否意味着总共有14K到22K的元素?或者矩阵是14000*14000到22000*22000?还有,你想要什么?你想节省时间吗?或者你想节省内存,准备牺牲一些时间?还是别的什么?同时,您提供的信息太少,无法给出有意义的答案。如果您不经常读取和写入,则可以存储更改列表,并根据需要合成修改后的矩阵。