[英]Linked 2D Matrix in C#
我需要在C#中實現這個場景:
矩陣將非常大,可能是10000x10000或更大。 我將在分層聚類算法中將其用於距離矩陣。 在算法的每次迭代中,矩陣都應該更新(將2行連接成1和2列為1)。 如果我使用簡單的雙[,]或雙[] []矩陣,這個操作將非常“昂貴”。 請問,任何人都可以建議這種情況的C#實現嗎?
你現在有算法嗎? 那貴是什么意思? 記憶還是時間昂貴? 如果內存昂貴:你可以用c#做多少。 但您可以考慮使用臨時對象在數據庫中執行計算。 如果時間昂貴:您可以使用並行性來連接列和行。
但除此之外,我認為一個簡單的double[,]
數組是你在c#中獲得的最快和內存節省方式,因為訪問數組值是一個o(1)操作,並且數組具有最少的內存和管理開銷(比較列表和詞典)。
如上所述,基本的double [,]將成為在C#中處理此問題的最有效方法。
請記住,C#位於托管內存的頂層,因此與低級別(就內存而言)操作相比,您對細粒度的控制較少。與基本C相比,在C#中創建自己的對象只會使用更多在這種情況下的內存,也可能會降低算法速度。
如果您尚未選擇算法, CURE似乎是一個不錯的選擇。 算法的選擇可能會影響您的數據結構選擇,但這不太可能。
您會發現該算法無論如何都能確定“成本”的理論極限。 例如,您將閱讀對於CURE,您受到O(n2 log n)運行時間和O(n)內存使用的約束。
我希望這有幫助。 如果您能提供更多詳細信息,我們可能會提供更多幫助!
N.
不可能“合並”兩行或兩列,你必須將整個矩陣復制到一個新的,較小的矩陣,這確實是不可接受的昂貴。
您可能只需將一行中的值添加到上一行,然后忽略這些值,就像刪除它們一樣。
數組的數組:double [] []實際上比double [,]更快。 但需要更多的記憶。
如果你稍微更改算法,可能不需要整個數組合並的東西,但這可能有助於你:
public static void MergeMatrix()
{
int size = 100;
// Initialize the matrix
double[,] matrix = new double[size, size];
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
matrix[i, j] = ((double)i) + (j / 100.0);
int rowMergeCount = 0, colMergeCount = 0;
// Merge last row.
for (int i = 0; i < size; i++)
matrix[size - rowMergeCount - 2, i] += matrix[size - rowMergeCount - 1, i];
rowMergeCount++;
// Merge last column.
for (int i = 0; i < size; i++)
matrix[i, size - colMergeCount - 2] += matrix[i, size - colMergeCount - 1];
colMergeCount++;
// Read the newly merged values.
int newWidth = size - rowMergeCount, newHeight = size - colMergeCount;
double[,] smaller = new double[newWidth, newHeight];
for (int i = 0; i < newWidth; i++)
for (int j = 0; j < newHeight; j++)
smaller[i, j] = matrix[i, j];
List<int> rowsMerged = new List<int>(), colsMerged = new List<int>();
// Merging row at random position.
rowsMerged.Add(15);
int target = rowsMerged[rowMergeCount - 1];
int source = rowsMerged[rowMergeCount - 1] + 1;
// Still using the original matrix since it's values are still usefull.
for (int i = 0; i < size; i++)
matrix[target, i] += matrix[source, i];
rowMergeCount++;
// Merging col at random position.
colsMerged.Add(37);
target = colsMerged[colMergeCount - 1];
source = colsMerged[colMergeCount - 1] + 1;
for (int i = 0; i < size; i++)
matrix[i, target] += matrix[i, source];
colMergeCount++;
newWidth = size - rowMergeCount;
newHeight = size - colMergeCount;
smaller = new double[newWidth, newHeight];
for (int i = 0, j = 0; i < newWidth && j < size; i++, j++)
{
for (int k = 0, m = 0; k < newHeight && m < size; k++, m++)
{
smaller[i, k] = matrix[j, m];
Console.Write(matrix[j, m].ToString("00.00") + " ");
// So merging columns is more expensive because we have to check for it more often while reading.
if (colsMerged.Contains(m)) m++;
}
if (rowsMerged.Contains(j)) j++;
Console.WriteLine();
}
Console.Read();
}
在這段代碼中,我使用兩個1D幫助器列表來計算包含數據的大數組的索引。 刪除行/列非常便宜,因為我只需要從幫助列表中刪除該索引。 但當然大數組中的內存仍然存在,即根據您的使用情況,您會發生內存泄漏。
public class Matrix
{
double[] data;
List<int> cols;
List<int> rows;
private int GetIndex(int x,int y)
{
return rows[y]+cols[x];
}
public double this[int x,int y]
{
get{return data[GetIndex(x,y)];}
set{data[GetIndex(x,y)]=value;}
}
public void DeleteColumn(int x)
{
cols.RemoveAt(x);
}
public void DeleteRow(int y)
{
rows.RemoveAt(y);
}
public Matrix(int width,int height)
{
cols=new List<int>(Enumerable.Range(0,width));
rows=new List<int>(Enumerable.Range(0,height).Select(i=>i*width));
data=new double[width*height];
}
}
嗯,對我來說,這看起來像一個簡單的二叉樹。 左側節點表示行中的下一個值,右側節點表示該列。
因此,迭代行和列並將它們組合起來應該很容易。
謝謝你的答案。
目前我正在使用這個解決方案:
public class NodeMatrix
{
public NodeMatrix Right { get; set;}
public NodeMatrix Left { get; set; }
public NodeMatrix Up { get; set; }
public NodeMatrix Down { get; set; }
public int I { get; set; }
public int J { get; set; }
public double Data { get; set; }
public NodeMatrix(int I, int J, double Data)
{
this.I = I;
this.J = J;
this.Data = Data;
}
}
List<NodeMatrix> list = new List<NodeMatrix>(10000);
然后我正在構建節點之間的連接。 之后矩陣准備就緒。
這將使用更多的內存,但我認為添加行和列,連接行和列等操作會更快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.