3d 三维稀疏矩阵的实现?

3d 三维稀疏矩阵的实现?,3d,sparse-matrix,3d,Sparse Matrix,我发现c#over有一个非常好的稀疏矩阵实现 但是当我在三维坐标系中工作时,我需要一个稀疏矩阵实现,我可以用它来映射三维坐标系 细节:我将大量的原始形状数据存储在内存中,就像立方体一样。我确实有很多(大约3000万),而且我有很多空(零)条目。考虑到我的每个条目花费1字节的条目,我想实现一个稀疏矩阵,这样我就可以相当节省内存空间 注意:快速访问矩阵单元对我来说是一个相当重要的因素,因此我会以速度而不是内存消耗为代价。我刚才提出的一个非常简单的解决方案是: public class Sparse3

我发现c#over有一个非常好的稀疏矩阵实现

但是当我在三维坐标系中工作时,我需要一个稀疏矩阵实现,我可以用它来映射三维坐标系

细节:我将大量的原始形状数据存储在内存中,就像立方体一样。我确实有很多(大约3000万),而且我有很多空(零)条目。考虑到我的每个条目花费1字节的条目,我想实现一个稀疏矩阵,这样我就可以相当节省内存空间


注意:快速访问矩阵单元对我来说是一个相当重要的因素,因此我会以速度而不是内存消耗为代价。

我刚才提出的一个非常简单的解决方案是:

public class Sparse3DMatrix<T>
{
    Dictionary<Tuple<int,int,int>, T> values = new Dictionary<Tuple<int, int, int>, T>();

    public T this[int x, int y, int z]
    {
        get { return values[new Tuple<int, int, int>(x, y, z)]; }
        set { values[new Tuple<int, int, int>(x, y, z)] = value; }
    }

    public bool ContainsKey(int x, int y, int z)
    {
        return values.ContainsKey(new Tuple<int, int, int>(x, y, z));
    }
}
公共类Sparse3DMatrix
{
字典值=新字典();
公共T这个[intx,inty,intz]
{
获取{返回值[新元组(x,y,z)];}
set{values[新元组(x,y,z)]=value;}
}
公共bool ContainsKey(整数x,整数y,整数z)
{
返回值.ContainsKey(新元组(x,y,z));
}
}
用法:

var test = new Sparse3DMatrix<float>();
test[1, 1, 1] = 1f;
Console.WriteLine(test[1, 1, 1]);
var test=new Sparse3DMatrix();
试验[1,1,1]=1f;
控制台写入线(测试[1,1,1]);
它可以用类似于他的版本的方法进行扩展,并检查
x、y、z
值等

我肯定有人对它的表现有话要说。这将是一个不错的实现,除非您真的需要它来实现高性能。这取决于
Tuple
的哈希代码实现和您的具体用法。如果我们假设散列是好的,我们将有
O(1)
查找时间。如果您知道将有很多元素,那么可以使用
新字典(初始容量)
来避免在添加项目时不必要地调整大小


与his不同,它只有一个包含所有项的
字典。他的版本有很多字典。his的好处是,如果您必须扫描整行,您只需迭代第二级字典(这对您没有帮助,因为您希望扫描列),这比单独查找项目更快。但是拥有一个单独的字典意味着更少的内存使用-尤其是当你每行只有很少的项目时。

你在三维坐标系中工作的事实不会改变你是否可以使用这个数据结构。可以使用与2D矩阵相同的稀疏矩阵来包含3D空间的矩阵;只是条目发生了变化

对于包含大量零项的大型矩阵,可以使用稀疏矩阵。这在物理问题的离散表示中是典型的,这些问题来自有限差分法和有限元法。它们具有围绕对角线聚集的非零条目的条带;对角线带外的条目通常为零。稀疏矩阵不会存储这些信息;必须编写像LU和QR这样的分解,以了解如何处理稀疏性

这些矩阵可以描述二维或三维空间中的问题

如果您认为您需要另一个数据结构,我相信您是错误的。

为什么不使用一个或类似的数据结构(例如八叉树)?
有很多C++实现,例如:

< p> Lasse Espeholt的解决方案是实用的,但是当它们被“零”或零化时,可以通过移除元素来改进。如果不这样做,矩阵或数组可能会失去稀疏性。这里有一个替代解决方案,它假设如果没有插入某个类型的元素,则该元素是该类型的默认元素。例如,对于
double
表示0.0,对于
string
表示
null

public class Sparse3DArray<T>
{
  private Dictionary<Tuple<int, int, int>, T> data = new Dictionary<Tuple<int, int, int>, T>();

  public int Nnz { get { return data.Count; } }

  public T this[int x, int y, int z]
  {
    get
    {
      var key = new Tuple<int, int, int>(x, y, z);
      T value;
      data.TryGetValue(key, out value);
      return value;
    }

    set
    {
      var key = new Tuple<int, int, int>(x, y, z);
      if (null == value)
        data.Remove(key);
      else if (value.Equals(default(T)))
        data.Remove(key);
      else
       data[key] = value;
     }
   }
}
公共类Sparse3DArray
{
私有字典数据=新字典();
public int Nnz{get{return data.Count;}}
公共T这个[intx,inty,intz]
{
得到
{
var key=新元组(x,y,z);
T值;
数据.TryGetValue(键,输出值);
返回值;
}
设置
{
var key=新元组(x,y,z);
if(null==值)
数据删除(键);
else if(value.Equals(默认值(T)))
数据删除(键);
其他的
数据[键]=值;
}
}
}

我会使用字典,但您可以使用单个long作为键,并使用它来存储坐标(前提是坐标较短),而不是使用
元组作为键。这将减少内存占用,甚至可能提高性能

private Dictionary<long, T> data = new Dictionary<long, T>();
private long GetKey(short x, short y, short z)
{
   return (x * 10000 + y) * 10000 + z;
}
private Dictionary data=new Dictionary();
专用长GetKey(短x、短y、短z)
{
返回(x*10000+y)*10000+z;
}

您的用例是什么?3D图形的变换矩阵?不,只是在问题中添加了细节。对,这是一个稀疏体素矩阵。30M是细胞总数,还是填充细胞数?如果我没记错的话,严格来说,矩阵是2D的。你想要一个稀疏的3D数组或者稀疏张量:稀疏矩阵对我来说很合适,因为正如你提到的,我的矩阵将包含很多零(空)项。但在这种情况下2D或3D是无关紧要的。