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

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

[[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億のブルーオーシャンが呼び寄せる、電力検査ロボットが最前線に

ブログ    
ブログ    

推薦する

JVM 世代別ガベージコレクションのプロセスとアルゴリズムの選択の図解説明

この記事は、JVM の世代別ガベージ コレクション プロセスを紹介し、さまざまなガベージ コレクショ...

Google Colab をマスターするための 20 のヒント

Google Colab は AI 開発者に無料の GPU を提供しており、Tensorflow や...

1 分以内に GPT アプリケーションを開発しましょう!さまざまな専門家が懸命に取り組んでおり、ネットユーザーは「ChatGPTは新しいiPhoneだ」と言っている

GPT はまだ正式にリリースされていませんが、誰かがすでに「先走って」いるのでしょうか? !ほら、社...

SAIC Maxus、クローズドループエコシステム構築に向けた「RVスマートモビリティビジョン」を発表

2017年6月30日、第一回世界知能大会で上汽大通の「RVスマートモビリティビジョン」が盛大に発表さ...

百度がスマートシティ向け「ACE計画」を発表、ロビン・リーはAI思考でインターネット思考に打ち勝ちたい

11月1日、北京で百度世界博覧会2018が開幕した。百度の創業者で会長兼CEOの李克強(ロビン・リー...

脚本を書いて、AIが動画を自動編集:編集者の7時間かけて作成した動画を13分で完成

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

ビッグデータと人工知能に関する冷静な考察

ビッグデータと人工知能は今年最もホットな話題であり、特に司法分野ではホットです。ビッグデータ時代の司...

KreadoAIのアップグレード版がオンラインになり、AIGC戦略の展開が加速しました

最近、Yidiantianxiaの最初のAIGC製品であるKreadoAIは、SHOPLINEとAm...

...

Dr. ByteのAIは大活躍、ワンクリックでボーカルと伴奏を完璧に分離

[[424966]]この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI...

...

Daguan Data: 推奨システムアルゴリズムの再ランキングの実践

インターネットの出現と普及は、大量の情報をユーザーにもたらし、情報化時代の情報需要を満たしました。し...

視覚的な手がかりに「マーカー」を追加することで、Microsoft と他の企業は GPT-4V をより正確かつ詳細にしました。

最近、大規模言語モデル (LLM) において大きな進歩が見られました。特に、Generative P...

誰も教えてくれないAI大規模導入の効率的なプロセス!

現在、AIに関するチュートリアルは数多くあります。オブジェクト検出、画像分類、NLP の実行方法、チ...

...