在C#中有没有更有效的方法来计算关联矩阵?

在C#中有没有更有效的方法来计算关联矩阵?,c#,algorithm,matrix,C#,Algorithm,Matrix,我使用带元组键的字典实现了一个算法,该算法工作正常,但速度非常慢。我有一套弦。我试图实现一个关联矩阵,其中A[“abc”,“bcde”]=2,两个字符串的重叠量。L中的元组是A中的键。L是排序数组=>A[L[i]]1) { 字符串LastItem1=L.Last().Item1; 字符串LastItem2=L.Last().Item2; 删除(最后一项1); 删除(最后一项2); 字符串newElement=merge(LastItem1,LastItem2); 添加(新元素); for(int

我使用带元组键的字典实现了一个算法,该算法工作正常,但速度非常慢。我有一套弦。我试图实现一个关联矩阵,其中
A[“abc”,“bcde”]
=2,两个字符串的重叠量。L中的元组是A中的键。L是排序数组=>A[L[i]]
List<string> words = new List<string>(wordsFromFile);

Dictionary<Tuple<string, string>, int> A = new Dictionary<Tuple<string, string>, int>();
List<Tuple<string, string>> L = new List<Tuple<string,string>>();
List words=新列表(wordsFromFile);
字典A=新字典();
列表L=新列表();
(我使用计数排序生成L。之后刷新矩阵和列表非常耗时:)

while(words.Count>1)
{
字符串LastItem1=L.Last().Item1;
字符串LastItem2=L.Last().Item2;
删除(最后一项1);
删除(最后一项2);
字符串newElement=merge(LastItem1,LastItem2);
添加(新元素);
for(int i=0;if.Key.Item1==LastItem1 | | f.Key.Item1==LastItem2 | | f.Key.Item2==LastItem1 | | f.Key.Item2==LastItem2.ToArray();
foreach(itemsToRemove中的变量项)
A.移除(项.键);
L.删除(L.Last());
对于(int i=0;if.Item1==LastItem1 | | f.Item2==LastItem2 | | f.Item1==LastItem2 | | f.Item2==LastItem1.ToArray();
foreach(listitemsToRemove中的var项)L.Remove(项);
listitemsToRemove=L.Where(f=>f.Item2==LastItem2.ToArray();
}
  • 很难读懂高度模糊的代码,但有一件事让我感到惊讶:

    L[i].第1项

    与字典相比,这是次优的。我想您可能希望保留排序,在这种情况下,您可以使用OrderedDictionary

  • 在您的案例中,您可以使用foreach循环优化的for循环。事实上,for循环在原始性能上更快,但在使用它的方式上却更快。你在L上查12次,L是一个列表。它不是一个数组,它是一个列表,所以在这样的列表中间挑选项目会随着时间的推移而失去速度。Foreach针对这种特定情况进行了优化,并且在迭代列表时,它的头对头速度更快(除非引入int计数器,在这种情况下for循环更快)

  • words[i]正在进行3次查找(与foreach循环相比效率低下),其中它将查找一次

  • 很难读懂高度模糊的代码,但有一件事让我感到惊讶:

    L[i].第1项

    与字典相比,这是次优的。我想您可能希望保留排序,在这种情况下,您可以使用OrderedDictionary

  • 在您的案例中,您可以使用foreach循环优化的for循环。事实上,for循环在原始性能上更快,但在使用它的方式上却更快。你在L上查12次,L是一个列表。它不是一个数组,它是一个列表,所以在这样的列表中间挑选项目会随着时间的推移而失去速度。Foreach针对这种特定情况进行了优化,并且在迭代列表时,它的头对头速度更快(除非引入int计数器,在这种情况下for循环更快)

  • words[i]正在进行3次查找(与foreach循环相比效率低下),其中它将查找一次


  • 字典速度惊人,这不是你的问题。你真的应该发布一个。字典速度惊人,这不是你的问题。你真的应该发布一个。
    列表基本上是一个数组,也许你把它与
    链接列表
    混淆了?特别是因为你谈到“通过记忆跟踪linkedlist”。这里没有。您的bullet#2似乎也在讨论链表,尽管它没有按名称这样说。它不是,它指的是循环性能。我将尝试找到一个链接添加到它。从研究中发现,对于基于索引的查找,数组似乎比c#中的列表更快,这意味着不需要多次将其作为数组进行查找,也可以缓存该结果(会有一些小的改进)。Foreach有助于实现这一点,但代价是额外增加2个运行时变量。如果您使用这些额外的变量,那么它可能是冒险的(有时)。计数不同(这里的是直接调度(实际上是内联的)的
    System.Collections.Generic.List.Count
    属性,链接的是
    System.Linq.Enumerable.Count()
    扩展方法,多态调度)
    列表
    基本上是一个数组,可能您有点困惑
                while (words.Count > 1)
                {
                    string LastItem1 = L.Last().Item1;
                    string LastItem2 = L.Last().Item2;
                    words.Remove(LastItem1);
                    words.Remove(LastItem2);
                    string newElement = merge(LastItem1, LastItem2);
                    words.Add(newElement);
                    for (int i = 0; i < words.Count; ++i)
                    {
                        if (words[i] == newElement)
                        {
                            Tuple<string, string> tmp = new Tuple<string, string>(newElement, newElement);
                            A[tmp] = 0;
                        }
                        else
                        {
                            Tuple<string, string> tmp = new Tuple<string, string>(newElement, words[i]);
                            A[tmp] = A[new Tuple<string, string>(LastItem2, words[i])];
                            tmp = new Tuple<string, string>(words[i], newElement);
                            A[tmp] = A[new Tuple<string, string>(words[i], LastItem1)];
                        }
                    }
                    var itemsToRemove = A.Where(f => f.Key.Item1 == LastItem1 || f.Key.Item1 == LastItem2 || f.Key.Item2 == LastItem1 || f.Key.Item2 == LastItem2).ToArray();
                    foreach (var item in itemsToRemove)
                        A.Remove(item.Key);
    
                    L.Remove(L.Last());
                    for (int i = 0; i < L.Count(); ++i)
                    {
                        if (L[i].Item1 == LastItem2 && L[i].Item2 != LastItem1 && L[i].Item2 != newElement && L[i].Item2 != LastItem2) L[i] = new Tuple<string, string>(newElement, L[i].Item2);
                        else if (L[i].Item2 == LastItem1 && L[i].Item1 != LastItem1 && L[i].Item1 != newElement && L[i].Item1 != LastItem2) L[i] = new Tuple<string, string>(L[i].Item1, newElement);
                    }
    
                    var listitemsToRemove = L.Where(f => f.Item1 == LastItem1 || f.Item2 == LastItem2 || f.Item1 == LastItem2 || f.Item2 == LastItem1).ToArray();
                    foreach (var item in listitemsToRemove) L.Remove(item);
                    listitemsToRemove = L.Where(f => f.Item2 == LastItem2).ToArray();
    
                }