アルゴリズムについて口頭で:
任意のグラフでアルゴリズムを分析します(簡単にするために、エッジには重みがありません)。
アルゴリズムのシーケンスは次のとおりです。
1.グラフの頂点を任意に選択します(灰色でマーク)。
2.ピークは、最初の頂点に関連付けられている(グレーでマークされている)順番に考慮されます(その後、グレーではなく黒になります)。
3.すべての頂点が黒く塗りつぶされるまで、マークされた(灰色の)頂点に対してステップ2が実行されます。
今は同じことですが、より技術的な言語で:
1.グラフ内の任意の頂点が選択され、キューに配置されます。
2.すでにキューにある頂点に隣接するグラフのすべての頂点がキューに配置され、その後、この頂点はキューからプッシュされます。
3.ステップ2は 、キュー内のすべての頂点に対して実行されます。
それでは、コード( C# )に直接行きましょう。
配列をグラフとして使用し、コンソールでプログラムします(たとえば、それで十分です)。 ところで、この例では、有向グラフを使用します。
初期変数を設定し、配列を埋めます。
Random rand = new Random(); Queue<int> q = new Queue<int>(); // , string exit = ""; int u; u = rand.Next(3, 5); bool[] used = new bool[u + 1]; // int[][] g = new int[u + 1][]; // for (int i = 0; i < u + 1; i++) { g[i] = new int[u + 1]; Console.Write("\n({0}) -->[", i + 1); for (int j = 0; j < u + 1; j++) { g[i][j] = rand.Next(0, 2); } g[i][i] = 0; foreach (var item in g[i]) { Console.Write(" {0}", item); } Console.Write("]\n"); }
gは配列の配列であり、最初のインデックスは作業対象の頂点を定義し、2番目の配列は頂点が接続されているか接続されていない頂点のインデックスを決定します(値が0の場合、接続されていないため、1が接続されている場合)。 つまり、たとえば、g [1] [5] = 0は、1番目から5番目の頂点に接続がないことを意味します(ただし、グラフが方向付けられているため、隣接行列は対称ではないため、g [1] [5] = 0の場合、これは、g [5] [1] = 0)を意味するものではありません。
used-訪問したピークを入力する論理配列。
実際には、アルゴリズム自体の動作をさらに進めます。
used[u] = true; //, ( ) q.Enqueue(u); Console.WriteLine(" {0} ", u + 1); while (q.Count != 0) { u = q.Peek(); q.Dequeue(); Console.WriteLine(" {0}", u + 1); for (int i = 0; i < g.Length; i++) { if (Convert.ToBoolean(g[u][i])) { if (!used[i]) { used[i] = true; q.Enqueue(i); Console.WriteLine(" {0}", i + 1); } } } }
while-キューが空になるまで実行されます。 各反復の開始時に、プッシュされたキュー要素の値を変数uに割り当てます。
for-すべての頂点を通過するループ。 まず、頂点に隣接する頂点が存在するかどうかを確認します。頂点が存在し、その頂点が訪問先の頂点の配列(使用済み配列)に追加されていない場合は、そこに追加し、キューに追加します。
実際には、ここがアルゴリズム全体です。 はい、おそらくフリルなしで、はるかに良いことができますが、私は良い例を探すのが好きな人に役立つことを期待して、教育目的のためだけに記事を書いています。
プログラムは次のようになります。
Bfs
static void Main(string[] args) { Random rand = new Random(); Queue<int> q = new Queue<int>(); // , string exit = ""; int u; do { Console.WriteLine(" ? "); if (Console.ReadLine() == "") { Console.WriteLine(" :"); u = Convert.ToInt32(Console.ReadLine()) - 1; if (u < 3) { Console.WriteLine(" . ."); u = rand.Next(3, 5); } } else u = rand.Next(3, 5); bool[] used = new bool[u + 1]; // int[][] g = new int[u + 1][]; // for (int i = 0; i < u + 1; i++) { g[i] = new int[u + 1]; Console.Write("\n({0}) -->[", i + 1); for (int j = 0; j < u + 1; j++) { g[i][j] = rand.Next(0, 2); } g[i][i] = 0; foreach (var item in g[i]) { Console.Write(" {0}", item); } Console.Write("]\n"); } used[u] = true; //, ( ) q.Enqueue(u); Console.WriteLine(" {0} ", u + 1); while (q.Count != 0) { u = q.Peek(); q.Dequeue(); Console.WriteLine(" {0}", u + 1); for (int i = 0; i < g.Length; i++) { if (Convert.ToBoolean(g[u][i])) { if (!used[i]) { used[i] = true; q.Enqueue(i); Console.WriteLine(" {0}", i + 1); } } } } Console.WriteLine(" ?"); exit = Console.ReadLine(); Console.Clear(); } while (exit != "" || exit != "lf"); Console.ReadKey(); }
それだけです ご清聴ありがとうございました!
PS経験豊富なプログラマーは、私のコードブロックを見て、私が誰であるかについての怒った投稿に加えて、より良い方法を書いて、良いアドバイスをうれしく思います-初心者にとって記事をより便利で快適にします。