您可以使用基於單元格的[row,col]的索引。由於數據在對角線上,因此將行索引和相關列存儲與數據存儲在一起的典型方法並不是最優的。下面是一些代碼,你可以用它來做到這一點:
public class SparseMatrix<T>
{
public int Width { get; private set; }
public int Height { get; private set; }
public long Size { get; private set; }
private Dictionary<long, T> _cells = new Dictionary<long, T>();
public SparseMatrix(int w, int h)
{
this.Width = w;
this.Height = h;
this.Size = w * h;
}
public bool IsCellEmpty(int row, int col)
{
long index = row * Width + col;
return _cells.ContainsKey(index);
}
public T this[int row, int col]
{
get
{
long index = row * Width + col;
T result;
_cells.TryGetValue(index, out result);
return result;
}
set
{
long index = row * Width + col;
_cells[index] = value;
}
}
}
static void Main()
{
var sm = new SparseMatrix<int>(512, 512);
sm[42, 42] = 42;
int val1 = sm[13, 13];
int val2 = sm[42, 42];
Console.WriteLine("VAL1 = " + val1); // prints out 0
Console.WriteLine("VAL2 = " + val2); // prints out 42
Console.ReadLine();
}
注意,當T是一個結構,您可能需要調用IsCellEmpty因爲得到一個單元格的內容將不爲空,將默認值爲那種類型。您還可以展開代碼,以便根據Size
屬性和_cells.Count
爲您提供快速「SparseRatio」。
編輯:
好吧,如果你有興趣的是速度,你可以做的空間權衡VS速度。而不是隻有一本字典,有三個!它將你的空間增加了三倍,但它讓你以任何想要的方式枚舉真正簡單。下面是一些新的代碼表明:
public class SparseMatrix<T>
{
public int Width { get; private set; }
public int Height { get; private set; }
public long MaxSize { get; private set; }
public long Count { get { return _cells.Count; } }
private Dictionary<long, T> _cells = new Dictionary<long, T>();
private Dictionary<int, Dictionary<int, T>> _rows =
new Dictionary<int, Dictionary<int, T>>();
private Dictionary<int, Dictionary<int, T>> _columns =
new Dictionary<int, Dictionary<int, T>>();
public SparseMatrix(int w, int h)
{
this.Width = w;
this.Height = h;
this.MaxSize = w * h;
}
public bool IsCellEmpty(int row, int col)
{
long index = row * Width + col;
return _cells.ContainsKey(index);
}
public T this[int row, int col]
{
get
{
long index = row * Width + col;
T result;
_cells.TryGetValue(index, out result);
return result;
}
set
{
long index = row * Width + col;
_cells[index] = value;
UpdateValue(col, row, _columns, value);
UpdateValue(row, col, _rows, value);
}
}
private void UpdateValue(int index1, int index2,
Dictionary<int, Dictionary<int, T>> parent, T value)
{
Dictionary<int, T> dict;
if (!parent.TryGetValue(index1, out dict))
{
parent[index2] = dict = new Dictionary<int, T>();
}
dict[index2] = value;
}
}
如果你想遍歷所有條目,使用_cells
。如果您希望給定列的所有行使用_columns
。如果您想要給定行中的所有列使用_rows
。
如果要按排序順序進行迭代,可以開始將LINQ添加到混合中,和/或使用帶有封裝條目的內部類的排序列表(它必須存儲行或列,並執行IComparable<T>
爲了排序工作)。
我更新了我的答案。那麼性能效率比空間效率更重要嗎?您說「處理稀疏矩陣的有效方法」,然後在您的用例中討論訪問數據的多種方式。 – 2009-04-16 19:48:42
我會說性能比空間效率更重要。無論如何,我們將處理大量的數據,所以我不介意只要速度更快就爲矩陣使用大量空間 – 2009-04-17 13:07:20