Tôi có biểu đồ hai chân và tôi đang tìm cách lặp lại hiệu quả nhất để chia thành các thành phần được kết nối. Phiên bản đệ quy của tôi đã bắt đầu tràn ngăn xếp trên các tập dữ liệu lớn. Tôi sẵn sàng chuyển từ bất kỳ ngôn ngữ/mã giả nào, nhưng để hoàn thành, tôi sẽ được mã hóa trong C#.Thuật toán thành phần kết nối lặp lại
Mã hiện tại của tôi chuyên về các loại dữ liệu của tôi. Một phân vùng là protein, một là phổ. Bản đồ và Set là C++ stdlib workalikes.
void recursivelyAssignProteinToCluster (long proteinId,
long clusterId,
Set<long> spectrumSet,
Map<long, Set<long>> spectrumSetByProteinId,
Map<long, Set<long>> proteinSetBySpectrumId,
Map<long, long> clusterByProteinId)
{
// try to assign the protein to the current cluster
var insertResult = clusterByProteinId.Insert(proteinId, clusterId);
if (!insertResult.WasInserted)
return;
// recursively add all "cousin" proteins to the current cluster
foreach (long spectrumId in spectrumSet)
foreach (var cousinProteinId in proteinSetBySpectrumId[spectrumId])
{
if (proteinId != cousinProteinId)
{
Set<long> cousinSpectrumSet = spectrumSetByProteinId[cousinProteinId];
recursivelyAssignProteinToCluster(cousinProteinId,
clusterId,
cousinSpectrumSet,
spectrumSetByProteinId,
proteinSetBySpectrumId,
clusterByProteinId);
}
}
}
Map<long, long> calculateProteinClusters (NHibernate.ISession session)
{
var spectrumSetByProteinId = new Map<long, Set<long>>();
var proteinSetBySpectrumId = new Map<long, Set<long>>();
var query = session.CreateQuery("SELECT pi.Protein.id, psm.Spectrum.id " + GetFilteredQueryString(FromProtein, ProteinToPeptideSpectrumMatch));
foreach (var queryRow in query.List<object[]>())
{
long proteinId = (long) queryRow[0];
long spectrumId = (long) queryRow[1];
spectrumSetByProteinId[proteinId].Add(spectrumId);
proteinSetBySpectrumId[spectrumId].Add(proteinId);
}
var clusterByProteinId = new Map<long, long>();
int clusterId = 0;
foreach (var pair in spectrumSetByProteinId)
{
long proteinId = pair.Key;
// for each protein without a cluster assignment, make a new cluster
if (!clusterByProteinId.Contains(proteinId))
{
++clusterId;
recursivelyAssignProteinToCluster(proteinId,
clusterId,
pair.Value,
spectrumSetByProteinId,
proteinSetBySpectrumId,
clusterByProteinId);
}
}
return clusterByProteinId;
}
Khi ShinTakezou đề xuất tôi đã tái cấu trúc để xếp chồng lên đống và hoạt động tốt. Tôi đã sử dụng phương pháp DepthFirstSearch từ ví dụ của digEmAll.
var clusterByProteinId = new Map<long, long>();
int clusterId = 0;
var clusterStack = new Stack<KeyValuePair<long, Set<long>>>();
foreach (var pair in spectrumSetByProteinId)
{
long proteinId = pair.Key;
if (clusterByProteinId.Contains(proteinId))
continue;
// for each protein without a cluster assignment, make a new cluster
++clusterId;
clusterStack.Push(new KeyValuePair<long, Set<long>>(proteinId, spectrumSetByProteinId[proteinId]));
while (clusterStack.Count > 0)
{
var kvp = clusterStack.Pop();
// try to assign the protein to the current cluster
var insertResult = clusterByProteinId.Insert(kvp.Key, clusterId);
if (!insertResult.WasInserted)
continue;
// add all "cousin" proteins to the current cluster
foreach (long spectrumId in kvp.Value)
foreach (var cousinProteinId in proteinSetBySpectrumId[spectrumId])
if (!clusterByProteinId.Contains(cousinProteinId))
clusterStack.Push(new KeyValuePair<long, Set<long>>(cousinProteinId, spectrumSetByProteinId[cousinProteinId]));
}
}
Đăng phương pháp đệ quy của bạn và ai đó ở đây sẽ dịch nó thành một phương pháp lặp lại cho bạn. – Brannon
khi đệ quy ăn quá nhiều ngăn xếp, lần đầu tiên giữ cùng một thuật toán, bạn có thể thử thay đổi đệ quy thành dữ liệu tiêu thụ vòng lặp (thông qua "pop") từ một ngăn xếp * (cuộc gọi đến cùng chức năng trở thành một cú đẩy chồng các đối số được yêu cầu cho hàm). Tất nhiên với "chồng" tôi có nghĩa là một người dùng thực hiện danh sách LIFO, và điều này cần một chút công việc, nhưng theo cách này bạn bị giới hạn bởi đống và không phải bởi ngăn xếp. (Có lẽ điều này hoạt động dễ dàng chỉ cho đệ quy đuôi? Tôi phải suy nghĩ về nó ...) – ShinTakezou
Bởi "thành phần", bạn có nghĩa là subgraphs? – Beta