グラフアルゴリズムシリーズ: 計算グラフにおける最短経路

グラフアルゴリズムシリーズ: 計算グラフにおける最短経路

[[398324]]

この記事はWeChatの公開アカウント「Beta Learns JAVA」から転載したもので、著者はSilently9527です。この記事を転載する場合は、Beta Learning JAVA パブリック アカウントにお問い合わせください。

序文

前の 2 つの記事では、深さ優先探索を使用して、グラフ内の頂点 v から頂点 w までのパスを見つけることができました。ただし、深さ優先探索は頂点の入力に大きく関係しており、見つかったパスは必ずしも最短ではありません。通常、map 関数など、グラフ内の最短パスを見つける必要があることがよくあります。ここでは幅優先探索アルゴリズムを使用する必要があります

幅優先探索

以前に定義されたパス検索APIを引き続き使用します

  1. パブリッククラスPaths{
  2. パス(グラフ グラフ、 int s);
  3.      
  4. boolean hasPathTo( int v); // s->v からのパスがあるかどうかを判定する
  5.      
  6. Iterable< Integer > pathTo( int v); //パスが存在する場合はパスを返す
  7. }

幅優先探索では、最短経路を見つけるために、再帰を使用してそれを達成するのではなく、開始点の順序ですべての頂点をトラバースする必要があります。アルゴリズムの考え方は次のとおりです。

  • マークされているが、隣接リストがまだ走査されていない頂点を格納するためにキューを使用します。
  • キューから次の頂点vを取り出してマークする
  • vに隣接するマークされていない頂点をすべてキューに追加します。

このアルゴリズムでは、パスを保存するために、エッジ配列 edgeTo[] を使用し、親リンク ツリーを使用して、ルート ノードから接続されているすべての頂点までの最短パスを表す必要があります。

  1. パブリッククラスBreadthFirstPaths {
  2. プライベートブール値 marked[];
  3. プライベートint []エッジTo;
  4. プライベートint s;
  5. プライベート Queue< Integer > queue = new LinkedListQueue<>();
  6.  
  7. パブリックBreadthFirstPaths(グラフグラフ、 int s) {
  8. this.s = s;
  9. this.marked = 新しいブール値[graph.V()];
  10. this.edgeTo = 新しいint [graph.V()];
  11.  
  12. bfs(グラフ, s);
  13. }
  14.  
  15. プライベートvoid bfs(グラフグラフ、 int s) {
  16. this.marked[s] = true ;
  17. this.queue.enqueue(s);
  18. while (!this.queue.isEmpty()) {
  19. 整数v = this.queue.dequeue();
  20. ( int w : graph.adj(v))の場合{
  21. if (!this.marked[w]) {
  22. this.marked[w] = true ;
  23. this.edgeTo[w] = v;
  24. this.queue.enqueue(w);
  25. }
  26. }
  27. }
  28.  
  29.  
  30. }
  31.  
  32. パブリックブール値hasPathTo( int v) {
  33. this.marked[v]を返します
  34. }
  35.  
  36. パブリックイテラブル<整数> pathTo( int v) {
  37. (!hasPathTo(v))の場合{
  38. 新しい IllegalStateException をスローします ( "s は v に到達できません" );
  39. }
  40. Stack<整数> stack = new LinkedListStack<>();
  41. スタックをプッシュします。
  42. (edgeTo[v] != s) の間 {
  43. スタックをプッシュします(edgeTo[v]);
  44. v = エッジ[v];
  45. }
  46. スタックをプッシュします。
  47. スタックを返します
  48. }
  49. }

次の図を列としてとらえ、幅優先探索の軌跡を見てみましょう。

ユニットテストコード:

  1. @テスト
  2. パブリックボイドテスト(){
  3. グラフ graph = new Graph(8);
  4. グラフにエッジを追加します。(0, 1);
  5. グラフにエッジを追加します(0, 2);
  6. グラフにエッジを追加します(0, 5);
  7. グラフにエッジを追加します。(1, 3);
  8. グラフにエッジを追加します。
  9. グラフにエッジを追加します(4, 3);
  10. グラフにエッジを追加します(5, 3);
  11. グラフにエッジを追加します(6, 7);
  12.  
  13. BreadthFirstPaths パス = new BreadthFirstPaths(graph, 0);
  14. システム.out.println (paths.hasPathTo(5));
  15. System.out.println (paths.hasPathTo(2)) ;
  16. システム.out.println (paths.hasPathTo(6));
  17.  
  18. paths.pathTo(5).forEach(System.out:: print );
  19. System.out.println( ) ;
  20. paths.pathTo(4).forEach(System.out:: print );
  21. System.out.println( ) ;
  22. paths.pathTo(2).forEach(System.out:: print );
  23. System.out.println( ) ;
  24. paths.pathTo(3).forEach(System.out:: print );
  25.  
  26. }

実行結果は、私たちが分析した走行軌跡と一致しています。

シンボル図

最近の記事で学んだグラフ アルゴリズムはすべて、数値を頂点として使用しています。これは、数値を使用してこれらのアルゴリズムを実装するのが非常に簡単で便利だからです。ただし、実際のシナリオでは、地図上の場所や映画と俳優の関係など、数値ではなく文字が頂点として使用されることがよくあります。

実際のシナリオに対応するには、数字と文字列のマッピングを作成する必要があります。このとき、前回の記事で実装したマップ(マップはバイナリツリー、赤黒木、ハッシュテーブルなどを通じて実装されます。興味のある学生は調べることができます)を考え、Mapを使用して文字列と数字のマッピング関係を維持します。

  1. パブリックインターフェースSymbolGraph {
  2. boolean contains (String key ); //頂点が存在するかどうかを判断します
  3.  
  4. 整数  index (String key ); //名前で対応するデジタル頂点を返す
  5.  
  6. String name ( int v); //デジタル頂点を通じて対応する文字名を返す
  7.  
  8. グラフ graph();
  9. }

実装のアイデア:

  • マップを使用して文字列と数値のマッピングを保存します。キーは文字列、値は数値です。
  • 配列を使用して、数値から文字列へのマッピングを逆にします。配列の添え字は数値の頂点に対応し、値は文字列名に対応します。
  • 構築されたグラフの頂点と辺が、a、b、c、d\nb、a、h、l、p\ng、s、z などの文字列で表されるとします。\n で区切られた各セグメントの最初の文字列は頂点 v を表し、次の文字列は頂点 v に接続された隣接頂点を表します。

実際のプロセスは、特定の状況に応じて決定されます。必ずしもこの種類の文字列である必要はありません。データベースまたはネットワーク要求から取得できます。

コードは次のように実装されます。

  1. パブリッククラスSymbolGraph {
  2. プライベート Map<String, Integer > map = new RedBlack23RedBlackTreeMap<>();
  3. プライベートString[]キー;
  4. プライベートグラフグラフ;
  5.  
  6. パブリックシンボルグラフ(文字列テキスト) {
  7. Arrays.stream(text.split( "\n" )).forEach(行 -> {
  8. 文字列[]を分割 = line.split( "," );
  9. ( int i = 0; i < split.length; i++) {
  10. map.put([i], i);
  11. }
  12. });
  13.  
  14. this.keys = 新しい文字列[ map.size ()];
  15. map.keys().forEach(キー-> {
  16. this.keys[this.map.get( key )] =キー;
  17. });
  18.  
  19. this.graph = 新しいグラフ(this.keys.length);
  20. Arrays.stream(text.split( "\n" )).forEach(行 -> {
  21. 文字列[]を分割 = line.split( "," );
  22. 分割されたマップ0に分割します。
  23. ( int i = 1; i < split.length; i++) {
  24. this.graph.addEdge(v, this.map.get(split[i]));
  25. }
  26. });
  27.          
  28. }
  29.  
  30. パブリックブール値には(文字列キー)が含まれます
  31. map.contains (キー)を返します
  32. }
  33.  
  34. 公共 整数 インデックス(文字列キー) {
  35. map.get(キー)を返します
  36. }
  37.  
  38. パブリック文字列( int  索引) {
  39. this.keys[インデックス]を返します
  40. }
  41.  
  42. パブリックグラフグラフ() {
  43. this.graphを返します
  44. }
  45.  
  46. 公共 静的void main(String[] args) {
  47. システム.out .println(Arrays.toString( "323\n2323" .split( "\n" )));
  48. }
  49. }

この記事のすべてのソースコードは、github リポジトリに保存されています: https://github.com/silently9527/JavaCore

<<:  AIに関する4つの最も一般的な誤解

>>:  50億のブルーオーシャンが呼び寄せる、電力検査ロボットが最前線に

ブログ    
ブログ    

推薦する

世界シミュレーターはAGIの最終成果、12の状況予測です!チーフエキスパートによる1万語の記事がソラのマイルストーンを専門的に解釈

私はここ数日、Sora の技術レポートと Sora のさまざまな技術分析を読んできました。基本的な視...

ニューラルネットワーク関係抽出のための構文的に敏感なエンティティ表現

ニューラル関係抽出のための構文的に敏感なエンティティ表現。関係抽出タスクの大規模な適用における大きな...

人工知能が医療に及ぼす12の影響

人工知能はヘルスケアに変革をもたらす力となることが期待されています。では、医師と患者は AI 駆動型...

マイクロソフトは小売業界で新たなスキルを解き放つために人工知能を推進

NRF 2024: Retail’s Big Show に先立ち、マイクロソフト社は、ショッピング体...

AIを活用してデジタル変革プロジェクトを改善する9つの方法

AI と ML テクノロジーが人気の話題になると、デジタル トランスフォーメーションの定義とビジネス...

産業インテリジェンスは「新しいインフラ」の下で非常に人気がありますが、まだ多くの問題があります

「新しいインフラ」が流行っています。これらは5G、人工知能、モノのインターネットなどの情報デジタルイ...

エンドツーエンドの自動運転における軌道予測の今後の方向性とは?最新レビューを最前線でお届け!

この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...

...

WatsonAIOps - AIの力を活用して、IT運用の効率とセキュリティの持続可能性を次のレベルに引き上げます

情報技術 (IT) 運用管理は、ミッションクリティカルなビジネス アプリケーションをサポートするため...

...

...

...

科学者たちはショウジョウバエの脳をハッキングしてNLPタスクを実行し、BERTよりも効率的であることを発見した。

人工ニューラルネットワークを長い間研究した後、動物の答えをコピーして貼り付ける方が良いのでしょうか?...

顔認識エンジンのトップ 5 (テキストにイースター エッグあり)

[51CTO.com クイック翻訳] ご存知のとおり、顔の特徴は指紋ほどユニークで永続的ではありま...