私はこの質問に対する回答をWeb上とこのサイトで数時間確認しようとしています。そこ。スタックサイズの変更を避け、C#でスタックオーバーフローを避けるには
.NETはアプリに1MBを割り当て、スタックサイズを強制するのではなく、再コーディングによってスタックオーバーフローを避けることをお勧めします。
私は、最大3000ノードまでうまく動作する「最短経路」アプリケーションを開発中です。そのノードはオーバーフローしています。ここで問題が発生する方法があります:
public void findShortestPath(int current, int end, int currentCost)
{
if (!weight.ContainsKey(current))
{
weight.Add(current, currentCost);
}
Node currentNode = graph[current];
var sortedEdges = (from entry in currentNode.edges orderby entry.Value ascending select entry);
foreach (KeyValuePair<int, int> nextNode in sortedEdges)
{
if (!visited.ContainsKey(nextNode.Key) || !visited[nextNode.Key])
{
int nextNodeCost = currentCost + nextNode.Value;
if (!weight.ContainsKey(nextNode.Key))
{
weight.Add(nextNode.Key, nextNodeCost);
}
else if (weight[nextNode.Key] > nextNodeCost)
{
weight[nextNode.Key] = nextNodeCost;
}
}
}
visited.Add(current, true);
foreach (KeyValuePair<int, int> nextNode in sortedEdges)
{
if(!visited.ContainsKey(nextNode.Key) || !visited[nextNode.Key]){
findShortestPath(nextNode.Key, end, weight[nextNode.Key]);
}
}
}//findShortestPath
参考のために、Nodeクラスは一つのメンバーを持っています
public Dictionary<int, int> edges = new Dictionary<int, int>();
グラフは[]です:
private Dictionary<int, Node> graph = new Dictonary<int, Node>();
私はopimizeしようとしました1回の反復(再帰?)から次の手続きまで必要以上に手荷物が運ばれないようにしますが、各ノードが1〜9のエッジを持つ100Kノードのグラフでは、1MBの制限をかなり早く打ちます。
とにかく、誰かが私にいくつかのポインタ(not like this)を与えることができれば、私はC#とコードの最適化に新しいです。
または、アルゴリズムがCLRによって末尾再帰形式に変換できることを確認できます。 – LBushkin
C#はtailcall命令を生成しません。特定のバージョンのジッタは、tailcall命令が使用されていなくても、テール再帰を使用して特定のメソッドを最適化できることに気付くでしょう。しかし、私たちがリリースしたほとんどのジッタにはこのような最適化がありません。あなたはそれに頼るべきではありません。 –
また、あなたのアドバイスは実際に行動可能ではありません。 *オリジナルのポスターは、「アルゴリズムを末尾の再帰的なフォームに変換できることを確認する」と正確にはどのようにしていますか?これは、ランタイムの実装の詳細を深く理解することを必要とする複雑なプロセスであり、ビルディング42の人以外の誰もが所有するとは思わないことを理解しています。 –