C++ 密集和稀疏矩阵的高效(时间和空间复杂性)数据结构

C++ 密集和稀疏矩阵的高效(时间和空间复杂性)数据结构,c++,algorithm,matrix,vector,C++,Algorithm,Matrix,Vector,我必须读取一个文件,其中存储了一个包含汽车的矩阵(1=BlueCar,2=RedCar,0=Empty) 我需要写一个算法来移动矩阵中的车辆: 蓝色的向下移动 红色的向右移动 有一个回合,所有蓝色的移动,一个回合移动所有红色的 在读取文件之前,我不知道矩阵的大小以及它是密集还是稀疏,因此我必须实现两个数据结构(一个用于密集,一个用于稀疏)和两个算法 我需要达到可能的最佳时间和空间复杂度 由于未知的矩阵大小,我认为应该将数据存储在堆上 如果矩阵是稠密的,我认为可以使用如下方法: short i

我必须读取一个文件,其中存储了一个包含汽车的矩阵(1=BlueCar,2=RedCar,0=Empty)

我需要写一个算法来移动矩阵中的车辆

  • 蓝色的向下移动
  • 红色的向右移动
  • 有一个回合,所有蓝色的移动,一个回合移动所有红色的
在读取文件之前,我不知道矩阵的大小以及它是密集还是稀疏,因此我必须实现两个数据结构(一个用于密集,一个用于稀疏)和两个算法

我需要达到可能的最佳时间和空间复杂度

由于未知的矩阵大小,我认为应该将数据存储在堆上

如果矩阵是稠密的,我认为可以使用如下方法:

short int** M = new short int*[m];
short int*  M_data = new short int[m*n];

for(int i=0; i< m; ++i) 
{
    M[i] = M_data + i * n;
}
vector< tuple< row, column, value >> sparseMatrix
否则,我可以做如下事情:

short int** M = new short int*[m];
short int*  M_data = new short int[m*n];

for(int i=0; i< m; ++i) 
{
    M[i] = M_data + i * n;
}
vector< tuple< row, column, value >> sparseMatrix
vector>稀疏矩阵
但找到下一个位置的问题仍然存在

可能这不是最好的方法,那么如何以有效的方式实现稀疏情况呢?(也使用独特的稀疏结构)

为什么不直接在文件上创建一个?(假设您的数据0,1,2以连续字节(或位)的形式存储在文件中,这些字节的位置也表示车辆的坐标)

这样,您就不需要分配额外的内存并读入所有数据,并且可以使用
M[i][j]
简单高效地访问数据

检查这些行将有利于一级缓存

对于非常稀疏的数据,您可以扫描数据一次,并在内存中保留一个空区域/块的列表(只需要存储startpos和size),然后在以后的运行中跳过(并在需要时调整)

使用内存映射,内存中只保留频繁访问的页面。这意味着一旦扫描了空区域,内存将只分配给频繁访问的非空区域(所有这些都将由内核自动完成-无需自己跟踪)

另一个好处是,您可以直接访问操作系统磁盘缓存。因此,无需在内核空间和用户空间之间不断复制和移动数据

为了进一步优化空间和内存使用,这些汽车可以存储在文件中的2位中

更新

我必须用openMP和MPI移动汽车。。。内存映射是否正确 还可以使用并发线程吗

您当然可以使用多线程,但不确定openMP是否是这里的最佳解决方案,因为如果您同时处理数据的不同部分,则可能需要检查一些重叠区域(即汽车可能从一个块移动到另一个块)

或者您可以让线程在块的中间部分工作,然后启动其他线程来执行边界(红色的车是一个字节,蓝色的车是一整行)


您还需要一个锁定机制来调整稀疏区域的列表。我认为最好的方法是启动单独的线程(当然,这取决于数据的大小)。

在一个类似的任务中,我只是利用了

压缩的行和列(在下一节中)存储格式 是最普遍的:他们绝对不会对 矩阵的稀疏结构,它们不存储任何不必要的数据 元素。另一方面,它们的效率不是很高,需要 一个系统中每个标量操作的间接寻址步骤 矩阵向量积或预条件器求解

对于时间和空间复杂性要求,您需要更具体一些。CSR需要为简单操作执行额外的索引步骤,但如果您只是执行简单的矩阵操作,则这只会带来少量开销


我只想提出std::map。这个问题实际上是一个经过大量研究的领域,目的是保持访问速度(和低缓存未命中率),同时降低内存。看各种各样的。这真的取决于你的矩阵。它是对称的吗?带宽是多少?你能重新排序吗?由于代码简单但性能非常好,其中一个更受欢迎的是aka“真正的稀疏存储方案”@CoryKramer。这些元素似乎代表了汽车的位置。汽车可以移动。对称性似乎不太可能……我在这方面没有受过良好的教育,我只是好奇“找到下一个位置的问题”,在地图上查找一对“USER 2672165”有什么不对吗?我将避免多态性方法,并考虑两个(可能排序)。每个向量只包含坐标。我没有指定在下一步中我必须使用openMP和MPI移动汽车。。。内存映射是否也适用于并发线程?谢谢您的建议。。。它可以通过一个实现解决密集和稀疏的情况,但即使你说“简单”,我也无法在web上找到关于如何做到这一点的有用示例。唯一的一个是:(我是C++新手)@rh0x-事实上,两种情况都只需要一个实现。使用内存映射,您可以在文件上创建一个“映射视图”,一旦创建,您就可以像访问内存一样访问数据(使用指针或[]等)-对于Linux签出,对于Windows-它没有看起来那么难,而且可以非常强大/快速。关于openMP和MPI,因为教授想让我们了解他们,所以必须使用这两种语言!我去找mmap谢谢you@rh0x-嗯。。openMP主要用于循环和其他小的代码块,在这些代码块中,数据可以很容易地分割成独立的部分(并且很容易在不需要大量代码的情况下快速引入多个线程)。在这种情况下,数据可以跨块“移动”,因此,如果可以使用openMP完成,则至少需要一些特殊编码。要学习openMP,请参阅其他示例