これは、インタビューのトリビア質問を最終的に適用できるケースのように聞こえます.O(1)メモリだけを使用してリンクされたリストでサイクルを見つけることができます。
この場合、リンクされたリストは列挙する要素のシーケンスです。2つの列挙子を使用し、1つは半分の速度で実行し、速いものが遅いものに実行される場合は、ループがあります。また、これはO(n^2)時間の代わりにO(n)時間になります。欠点は、ノードのいくつかが複数回処理された後のループについてだけ見つけ出すことです。
この例では、「半分の速度」の方法を、より簡単に書ける「ドロップマーカー」方法に置き換えました。
class GenTreeNode {
...
///<summary>Wraps an the enumeration of linked data structures such as trees and linked lists with a check for cycles.</summary>
private static IEnumerable<T> CheckedEnumerable<T>(IEnumerable<T> sub_enumerable) {
long cur_track_count = 0;
long high_track_count = 1;
T post = default(T);
foreach (var e in sub_enumerable) {
yield return e;
if (++cur_track_count >= high_track_count) {
post = e;
high_track_count *= 2;
cur_track_count = 0;
} else if (object.ReferenceEquals(e, post)) {
throw new Exception("Infinite Loop");
}
}
}
...
///<summary>Enumerates the tree's nodes, assuming no cycles</summary>
private IEnumerable<GenTreeNode> tree_nodes_unchecked() {
yield return this;
foreach (var child in this.nodes)
foreach (var e in child.tree_nodes_unchecked())
yield return e;
}
///<summary>Enumerates the tree's nodes, checking for cycles</summary>
public IEnumerable<GenTreeNode> tree_nodes()
{
return CheckedEnumerable(tree_nodes_unchecked());
}
...
void ProcessTree() {
foreach (var node in tree_nodes())
proceess(node);
}
}
バイナリツリーにはサイクルというものはありません。正しい家系図データでさえ、バイナリツリーではありません。私は質問を編集して "グラフ" – Triptych
が好奇心をそそりました。これは、(サーブブレッドのように)投与量指数、Werk Nick Ratingか何かを調べるためのものですか? – nlucaroni
いいえ...私は馬の血統全体をファイルにエクスポートしています。私は近親交配を検出するためにも使用しますが、私のソフトウェア製品は特定の品種ではないため、私は分析する歴史的データはあまりありません。 – Romias