有簡單的方法來解決並行化問題,分離數據。從原始數據結構中讀取並寫入新的。這樣你就可以並行運行而不需要鎖定。
但可能並行化甚至沒有必要,數據結構並不高效。你使用字典的地方陣列就足夠了(因爲我知道代碼你有頂點0..result.Count-1
)。和List<int>
查找。 List.Contains
效率很低。 HashSet
會更好。或者,對於更密集的圖,BitArray
。所以,而不是Dictionary<int, List<int>>
您可以使用BitArray[]
。
我重寫了算法並做了一些優化。它不會製作圖形的簡單副本並刪除邊緣,只會從右邊緣構建新圖形。它使用BitArray[]
作爲輸入圖,List<int>[]
用於最終圖,因爲後者更稀疏。
int sizeOfGraph = 1000;
//create vertices of a graph
BitArray[] inputGraph = new BitArray[sizeOfGraph];
for (int i = 0; i < inputGraph.Length; ++i)
{
inputGraph[i] = new BitArray(i);
}
//fill random edges
Random rand = new Random(10);
for (int i = 1; i < inputGraph.Length; ++i)
{
BitArray vertex_i = inputGraph[i];
for(int j = 0; j < vertex_i.Count; ++j)
{
if(rand.Next(0, 100) < 50) //50% fill ratio
{
vertex_i[j] = true;
}
}
}
//create transitive closure
for (int i = 0; i < sizeOfGraph; ++i)
{
BitArray vertex_i = inputGraph[i];
for (int j = 0; j < i; ++j)
{
if (vertex_i[j]) { continue; }
for (int r = j + 1; r < i; ++r)
{
if (vertex_i[r] && inputGraph[r][j])
{
vertex_i[j] = true;
break;
}
}
}
}
//create transitive reduction
List<int>[] reducedGraph = new List<int>[sizeOfGraph];
Parallel.ForEach(inputGraph, (vertex_i, state, ii) =>
{
{
int i = (int)ii;
List<int> reducedVertex = reducedGraph[i] = new List<int>();
for (int j = i - 1; j >= 0; --j)
{
if (vertex_i[j])
{
bool ok = true;
for (int x = 0; x < reducedVertex.Count; ++x)
{
if (inputGraph[reducedVertex[x]][j])
{
ok = false;
break;
}
}
if (ok)
{
reducedVertex.Add(j);
}
}
}
}
});
MessageBox.Show("Finished, reduced graph has "
+ reducedGraph.Sum(s => s.Count()) + " edges.");
編輯
我寫了這個: 的代碼有一些問題。隨着方向i
現在,您可以刪除您需要的邊緣,結果將是不正確的。原來這是一個錯誤。我是這樣想的,讓有圖
1->0
2->1, 2->0
3->2, 3->1, 3->0
頂點2得到由頂點1減少,所以我們必須
1->0
2->1
3->2, 3->1, 3->0
現在頂點3被通過頂點2
1->0
2->1
3->2, 3->0
減少我們有一個問題,因爲我們不能減少3->0
因爲減少2->0
在這裏留下。但這是我的錯誤,這絕不會發生。內循環進入嚴格從低到高,所以不是
頂點3得到由頂點1
1->0
2->1
3->2, 3->1
降低,現在由頂點2
1->0
2->1
3->2
而結果是正確的。我爲錯誤表示歉意。
「線程安全字典」的搜索Stackoverflow – jdweng
該圖是傳遞閉包嗎?否則,這是行不通的(考慮1-> 2,2-> 3,3-> 4,1-> 4)。 –
是的。如果不是,Hasse圖不能形成。 – Storm