簡體   English   中英

C#中鏈接的2D矩陣

[英]Linked 2D Matrix in C#

我需要在C#中實現這個場景:

http://i.stack.imgur.com/Dm6G3.jpg

矩陣將非常大,可能是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM