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

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

[[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 アルゴリズムを使用して数十億のデータのパーセンタイルを計算するのでしょうか?

ブログ    
ブログ    

推薦する

香港大学の黄凱斌氏:6G時代のエッジインテリジェンス、シャノンとチューリングの出会い

この記事はLeiphone.comから転載したものです。転載する場合は、Leiphone.com公式...

...

ロボットは電気羊の夢を見るか?Google AI 従業員の辞職から AI 倫理について何を学ぶことができるか?

2月20日、Googleの倫理AIチームの創設者であるミッチェル氏はTwitterに「私は解雇され...

ちょうど今、人工知能に関する大きなニュースが発表されました

中国における人工知能熱の高まりは、テクノロジーとビジネスによって推進されているだけでなく、政府の推進...

では、機械学習とディープラーニングの違いは何でしょうか?

ディープラーニングは機械学習アルゴリズムのサブクラスであり、より複雑であることが特徴です。したがって...

データに飽きた?人工知能は良い選択です

今日のデジタル マーケティング担当者にとっての課題は、共感を得るためにすべてのプラットフォームでブラ...

新しいNeRF技術は、ビデオを簡単に制御できる3Dモデルに変換できます。

翻訳者 |ブガッティレビュー | Chonglou人間の動きが複雑で、環境によって見た目が微妙に異な...

GPT-4よりも優れた20億パラメータモデルは、ほぼ100%の精度で算術問題を解く

現在、大規模言語モデル (LLM) は、NLP の分野におけるさまざまな下流タスクの処理において優れ...

GPTは「贅沢」すぎるが、代替案が多数用意されており、展開の問題を心配する必要はもうない

近年、生成的事前トレーニング済みモデル (GPT など) の台頭により、自然言語処理の分野に革命が起...

暗号化アルゴリズムの鍵交換は少し安全ではない

今日は対称暗号化アルゴリズムの重要な問題についてお話ししましょう。暗号化の基本的な概念に精通していな...

2023 年までにデータセンターで注目される AI と ML の 10 大アプリケーション

人工知能 (AI) と機械学習 (ML) は、データセンター分野の重要なテクノロジーとなっています。...

コンピューティングパワーがボトルネックにならないように、Xiaohongshu の機械学習の異種ハードウェア推論を最適化する方法

多くの企業が GPU コンピューティング能力の開発を組み合わせて、自社の機械学習の問題に対するソリュ...

...

WAVE SUMMITが今年もやって来ました! AI 開発者の饗宴がこの寒い冬を盛り上げます!

WAVE SUMMIT+ ディープラーニング開発者カンファレンス 2023 が 12 月 28 日...