グラフアルゴリズムシリーズ: 無向グラフのデータ構造

グラフアルゴリズムシリーズ: 無向グラフのデータ構造

[[393944]]

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

序文

この記事から、グラフ関連のアルゴリズムを一緒に学習します。グラフ コンピューティングには、ガベージ コレクターのマーク アンド スイープ アルゴリズム、マップ上のパスの最短距離、トポロジカル ソートなど、非常に実用的なアルゴリズムが多数あります。これらのアルゴリズムを学習する前に、まずグラフの基本的な定義と、グラフを表すために使用されるデータ構造を理解する必要があります。この記事では、無向グラフから始めます。

グラフの定義

グラフ: 頂点の集合と、2 つの順序を接続できる順序の集合で構成されます。 2 つの頂点を結ぶ辺には方向がなく、このようなグラフは無向グラフと呼ばれます。

グラフ用語

同じ辺で接続された 2 つの頂点は隣接していると呼ばれます。

頂点の次数とは、この頂点を結ぶ辺の総数です。上図に示すように、頂点1の次数は3です。

頂点をそれ自身に接続する辺は自己ループと呼ばれます。

同じ頂点のペアを結ぶ辺は平行辺と呼ばれる。

他にもたくさんの用語があります。今のところ、この記事で使用する必要のある用語のみをリストします。他の用語については後で説明します。用語が多すぎると覚えるのは簡単ではありません。

グラフの表現方法

グラフを表現するために使用されるデータ構造は、主に次の 2 つの要件を指します。

  1. グラフ関連のアルゴリズムを開発する場合、グラフ表現のデータ構造が基礎となるため、このデータ構造が効率的です。
  2. 実際のプロセスでは、グラフのサイズは不確実であり、非常に大きくなる可能性があるため、十分なスペースを確保する必要があります。

これら 2 つの要件を考慮した後、専門家は次の 3 つの選択方法を提案しました。

  • 隣接行列は、v 個の頂点を持つグラフに入力されます。v に v を掛けた行列を使用して表すことができます。頂点 v が w に接続されている場合は、v 行と w 列を true に設定します。これにより、2 つの頂点が接続されていることが示されます。ただし、この方法には問題があります。グラフが非常に大きい場合、スペースが無駄になります。 2番目のポイントは満たされていません。第二に、この方法では平行なエッジを表現することができない。
  • エッジの配列は、頂点を表す 2 つの int 属性を含むエッジ オブジェクトを定義できます。ただし、頂点の接続された頂点を見つける必要がある場合は、すべてのエッジをトラバースする必要があります。このデータ構造は効率が悪い
  • 隣接リスト配列は、頂点の数と同じサイズの配列を定義します。データの添え字は頂点を表します。配列内の各要素はリンクリストオブジェクト (LinkedListQueue) であり、リンクリストに格納されている値は、頂点に接続されている頂点です。 (LinkedListQueueは以前の記事で実装されています。記事「https://juejin.cn/post/6926685994347397127」を参照してください)

無向グラフのAPI定義

  1. パブリッククラスGraph {
  2. public Graph( int V); // v 個の頂点と辺のないグラフを作成する
  3.      
  4. 公共  int V(); //頂点の数を返す
  5.      
  6. 公共  int E(); //グラフ内のエッジの総数を返す
  7.      
  8. public void addEdge( int v, int w); //グラフにエッジvWを追加する
  9.          
  10. public Iterable< Integer > adj( int v); // v に隣接するすべての頂点を返す
  11.      
  12. public String toString(); //文字列を使用してグラフの関係を出力します
  13. }

無向グラフAPIの実装

上記で定義した API を実装するには、3 つのメンバー変数が必要です。v はグラフ内の頂点の数を表し、e はグラフの合計エッジ データを表し、LinkedListQueue 配列は頂点 v の隣接ノードを格納するために使用されます。

コンストラクタは空の隣接リスト配列を初期化する

これは無向グラフなので、addEdge メソッドはグラフに v->w エッジと w->v エッジの両方を追加する必要があります。

  1. パブリッククラスGraph {
  2. プライベート最終int v;
  3. プライベートint e;
  4. プライベート LinkedListQueue< Integer >[] adj;
  5.  
  6. パブリックグラフ( int v) {
  7. this.v = v;
  8. this.adj = (LinkedListQueue< Integer >[]) 新しいLinkedListQueue[v];
  9. ( int i = 0; i < v; i++)の場合{
  10. this.adj[i] = 新しいLinkedListQueue<>();
  11. }
  12. }
  13.  
  14. 公共 整数V(){
  15. vを返します
  16. }
  17.  
  18. 公共 整数E() {
  19. eを返します
  20. }
  21.  
  22. パブリックvoid addEdge( int v, int w) {
  23. this.adj[v].enqueue(w);
  24. this.adj[w].enqueue(v);
  25. this.e++;
  26. }
  27.  
  28. パブリックイテラブル<整数> adj( int v) {
  29. this.adj[v]を返します
  30. }
  31.  
  32. @オーバーライド
  33. パブリック文字列toString() {
  34. StringBuilder sb = 新しい StringBuilder();
  35. sb.append(v).append( " 頂点、 " ).append(e).append( " 辺\n" );
  36. ( int i = 0; i < v; i++)の場合{
  37. sb.append(i).append( ": " );
  38. ( int j : this.adj[i])の場合{
  39. sb.append(j).append( " " );
  40. }
  41. sb.append( "\n" );
  42. }
  43. sb.toString()を返します
  44. }
  45. }

グラフの一般的なツールと方法

グラフデータ構造の実装に基づいて、いくつかのツールと方法を提供することができます。

頂点 v の次数を計算します。頂点の次数は、その頂点に接続されている頂点の数に等しくなります。

  1. 公共 静的  int degree(グラフグラフ、 int v) {
  2. 度数= 0;
  3. ( int w : graph.adj(v))の場合{
  4. 学位++;
  5. }
  6. 戻り度合い;
  7. }

すべての頂点の最大次数を計算する

  1. 公共 静的  int maxDegree(グラフグラフ) {
  2. 最大度数= 0;
  3. ( int v = 0; v < graph.V(); v++)の場合{
  4. int度 = 度(グラフ、v);
  5. (最大度数<度数)の場合{
  6. 最大度数 = 度数;
  7. }
  8. }
  9. maxDegreeを返します
  10. }

すべての頂点の平均次数を計算します。各辺には 2 つの頂点があるため、グラフ内のすべての頂点の合計次数は辺の 2 倍になります。

  1. 公共 静的  double avgDegree(グラフグラフ) {
  2. 2.0 * graph.E() / graph.V()を返します
  3. }

グラフ内の自己ループの数を計算します。頂点 v について、v が v の隣接リストにも表示される場合、v には自己ループがあります。無向グラフであるため、各エッジは 2 回記録されます (理解しにくい場合は、グラフの toString を出力して理解することができます)

  1. 公共 静的  int numberOfSelfLoops(グラフグラフ) {
  2. 整数 カウント= 0;
  3. ( int v = 0; v < graph.V(); v++)の場合{
  4. ( int w : graph.adj(v))の場合{
  5. (v == w) の場合 {
  6. カウント++;
  7. }
  8. }
  9. }
  10. 戻る カウント/ 2;
  11. }

要約する

この記事では、主にグラフを表現するために使用するデータ構造について学習し、このデータ構造に基づいていくつかの簡単なツールとメソッドを実装します。次の記事では、グラフの最初の検索アルゴリズムである深さ優先検索について学習します。

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

<<:  Nvidia の新しいブラック テクノロジーが「Minecraft」のモザイクをリアルな大ヒット作に変える

>>:  ElasticSearch はどのようにして TDigest アルゴリズムを使用して数十億のデータのパーセンタイルを計算するのでしょうか?

ブログ    
ブログ    
ブログ    

推薦する

AI 駆動型スマートビルは将来のトレンドになるでしょうか?

人工知能 (AI) は、建物の管理と制御の方法に革命をもたらし、これまで以上に効率的でコスト効率の高...

...

大規模な商用利用が間近に迫り、自動運転には明るい未来がある

自動運転は現在、自動車産業の主要な発展方向の一つとなり、社会全体が注目する技術テーマとなっています。...

ニューラル ネットワーク モデルの構築に適した最適化アルゴリズムはどれですか? 35,000件の検査でわかる

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

ChatGPT がリリースされてから 1 年が経ちました。主要なオープン ソース モデルはすべて追いついたのでしょうか?

1年前の今日、ChatGPTが誕生し、人工知能の新しい時代が到来したように思えました。 ChatG...

市場規模は100億を超え、マシンビジョンはブルーオーシャンの傾向を示す

マシンビジョンとは、人間の目の代わりに機械を使って物事を測定・判断し、その判断結果に基づいて現場の設...

「Painted Skin」の悪夢が現実に? 「人間の皮膚」で覆われたこのロボットはCell誌に掲載された。

指が背中をゆっくりと優しくなぞり、背骨に沿って上へ移動し、そしてゆっくりと止まるところを想像してくだ...

データサイエンス プロジェクトに Scikit-learn Python ライブラリを使用する方法

[[246038]]柔軟で多様な Python ライブラリは、データ分析とデータマイニングのための強...

モデル量子化とエッジAIがインタラクションを定義する方法

AI とエッジ コンピューティングの融合により、多くの業界が変革されるでしょう。移植性を向上させ、モ...

張亜琴氏と張宏江氏は人工知能の将来について何を語っているのでしょうか?

「大規模なシステムを構築するには、体系的な思考、実践的なスキル、システム構築への愛情を持った人材が...

...

最高裁判所は顔認識に関する司法解釈を発表し、無作為の「顔スキャン」に「ノー」と述べた。

今朝(8日)、第13期全国人民代表大会第5回会議第二回全体会議が開催され、最高人民法院と最高人民検察...

最大フロー問題の解決における画期的な進歩: 新しいアルゴリズムは「驚くほど高速」

この問題はネットワークフロー理論において非常に基本的なものです。 「新しいアルゴリズムは驚くほど高速...

エンジニアリングチームでよく使用される 6 つの AI ツール

アレックス・オメイヤー翻訳者 | 陳俊レビュー | Chonglou人工知能(AI)の急速な進化と発...

実践的なスキル: システムレベルからディープラーニングコンピューティングを最適化するにはどうすればよいでしょうか?

画像、音声認識、自然言語処理、強化学習などの多くの技術分野において、ディープラーニングは非常に効果的...