3D稀疏矩阵实现?

时间:2011-03-31 10:59:36

标签: 3d sparse-matrix

我已经为c#over http://www.blackbeltcoder.com/Articles/algorithms/creating-a-sparse-matrix-in-net找到了一个非常好的稀疏矩阵实现。

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

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

注意:快速访问矩阵单元对我来说是一个相当重要的因素,所以我的交易速度超过内存消耗。

5 个答案:

答案 0 :(得分: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));
    }
}

用法:

var test = new Sparse3DMatrix<float>();
test[1, 1, 1] = 1f;
Console.WriteLine(test[1, 1, 1]);

可以使用他的版本所具有的方法进行扩展,并检查x, y, z值等。

我确信有人会对其表现有所说明。除非你真的需要高性能的东西,否则这将是一个不错的实现。这取决于Tuple的哈希码实现以及您的具体用法。如果我们假设哈希值很好,我们将有O(1)个查找时间。如果您知道自己将拥有大量元素,则可以使用new Dictionary<...>(initial capacity)来避免在添加项目时不必要的大小调整。

与他的不同,这只有一个Dictionary包含所有项目。他的版本有字典词典。他的好处是,如果你必须扫描整行,你可以只迭代二级字典(这不会帮助你想要扫描列),这比单独查找项目更快。但是使用单个字典意味着更少的内存使用量 - 特别是当你每行的项目很少时。

答案 1 :(得分:1)

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;
     }
   }
}

答案 2 :(得分:0)

您在3D坐标系中工作的事实不会改变您是否可以使用此数据结构。可以使用与2D矩阵相同的稀疏矩阵来包含3D空间的矩阵;它只是改变的条目。

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

这些基质可以描述2D或3D空间中的问题。

如果您认为自己需要其他数据结构,我认为您是错误的。

答案 3 :(得分:0)

为什么不使用KD-Tree或类似的数据结构(例如八叉树)? 有很棒的c ++实现,例如:FLANN

答案 4 :(得分:0)

我将使用字典,但是可以使用单个long作为键并使用它来存储坐标(如果它们是短键),而不是使用Tuple<int, int, int>作为键。这样可以减少内存占用,甚至可以提高性能。

private Dictionary<long, T> data = new Dictionary<long, T>();
private long GetKey(short x, short y, short z)
{
   return (x * 10000 + y) * 10000 + z;
}