C#中的关联矩阵是否有更有效的方法?

时间:2017-05-02 01:11:48

标签: c# algorithm matrix

我使用带有元组键的字典实现了一个算法,算法有效,但速度非常慢。我有一组字符串。我试图实现一个关联矩阵,其中A["abc","bcde"] = 2,两个字符串的重叠量。 L中的元组是A中的键.L是排序数组=> A [L [i]]< A [L [I + 1]] 我将两个字符串合并到集合中最大的重叠,然后我更新"矩阵"和L列表。我在循环中执行它,直到该集合只有1个元素。我的问题是,使用字典算法太慢了。有没有更有效的方法来做到这一点?这是我的代码:

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>>();

(我使用计数排序来制作L.在刷新矩阵之后,列表非常耗时:)

            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();

            }

1 个答案:

答案 0 :(得分:0)

  1. 难以阅读高度混淆的代码,但有一件事突然出现在我身上:

    L [I] .Item1

    与字典相比,这是次优的。我想你可能想要保留订购,在这种情况下你可以使用OrderedDictionary&lt;&gt;

  2. 您使用的for循环可以在您的案例中通过foreach循环进行优化。确实,for循环的原始性能更快,但不是你使用它的方式。你在L上做了大约12次查找,这是一个列表。它不是一个数组,它是一个列表,因此在列表中间挑选项目会随着时间的推移而失去速度。 Foreach针对这种特定情况进行了优化,如果迭代一个列表,则会更快速地进行头对头(除非你引入一个int计数器,在这种情况下循环更快)。

  3. 单词[i]正在进行3次查找(与foreach循环相比效率低下),它会查找一次