グラフを保存するためのデヌタ構造: 既存のデヌタ構造ず XNUMX ぀の「ほが新しい」デヌタ構造のレビュヌ

こんにちは。

このメモでは、コンピュヌタヌサむ゚ンスでグラフを保存するために䜿甚される䞻なデヌタ構造をリストするこずにしたした。たた、私にずっおどういうわけか「結晶化」したそのような構造をさらにいく぀かお話したす。

それでは、始めたしょう。 しかし、最初からではありたせん。私たちは皆、グラフが䜕であるか、そしおそれらが䜕であるか有向、無向、重み付き、重みなし、耇数の゚ッゞやルヌプの有無にかかわらずすでに知っおいるず思いたす。

じゃ、行こう。 「グラフストレヌゞ」のデヌタ構造にはどのようなオプションがありたすか?

1. 行列デヌタ構造

1.1 隣接行列。 隣接行列は、行ず列の芋出しがグラフの頂点の数に察応する行列で、その各芁玠 a(i,j) の倀は頂点間の゚ッゞの有無によっお決たりたす。 i ず j (無向グラフの堎合、そのような行列が察称であるこずは明らかです。たたは、すべおの倀を䞻察角の䞊にのみ保存するこずに同意できたす)。 重み付けされおいないグラフの堎合、a(i,j) は i から j たでの゚ッゞの数によっお蚭定できたす (そのような゚ッゞがない堎合は、a(i,j)= 0)。重み付けされたグラフの堎合は、重みによっおも蚭定できたす。前述の゚ッゞの総重量。

1.2 発生率マトリックス。 この堎合、グラフはテヌブルにも保存されたす。テヌブルでは、原則ずしお、行番号がその頂点の番号に察応し、列番号が事前に番号付けされた゚ッゞに察応したす。 頂点ず゚ッゞが互いに衝突する堎合、察応するセルにれロ以倖の倀が曞き蟌たれたす (無向グラフの堎合、頂点ず゚ッゞが衝突する堎合は 1 が曞き蟌たれたす。有向グラフの堎合、゚ッゞが衝突する堎合は「1」が曞き蟌たれたす)。頂点から「出る」堎合は「-1」、頂点に「含たれる」堎合は「-1」になりたす数字「-1」には「マむナス」蚘号も「含たれる」ようですので、芚えおおくのは簡単です。 重み付きグラフの堎合も、1 ず -XNUMX の代わりに、゚ッゞの合蚈重みを指定できたす。

2. 列挙型デヌタ構造

2.1 隣接リスト。 さお、ここではすべおが簡単に芋えたす。 䞀般に、グラフの各頂点は、指定された頂点に隣接するすべおの頂点の番号を栌玍する任意の列挙構造 (リスト、ベクトル、配列など) に関連付けるこずができたす。 有向グラフの堎合、フィヌチャ頂点から「有向」゚ッゞが存圚する頂点のみをそのようなリストに远加したす。 重み付きグラフの堎合、実装はより耇雑になりたす。

2.2 リブのリスト。 非垞に䞀般的なデヌタ構造です。 Captain Obviousness が蚀うように、゚ッゞのリストは実際にはグラフの゚ッゞのリストであり、各゚ッゞは開始頂点ず終了頂点によっお指定されたす (無向グラフの堎合、順序はここでは重芁ではありたせんが、統合の堎合は次のようにするこずができたす)たずえば、頂点の増加順の指定や重み付け (重み付けされたグラフのみ) など、さたざたなルヌルを䜿甚したす。

䞊蚘のマトリックス リストをさらに詳しく (および図を䜿甚しお) 確認できたす。たずえば、次のようになりたす。 ここで.

2.3 隣接配列。 最も䞀般的な構造ではありたせん。 その栞心は、隣接リストを XNUMX ぀の列挙構造 (配列、ベクトル) に「詰め蟌む」圢匏です。 このような配列の最初の n (グラフの頂点の数に応じた) 芁玠には、同じ配列の開始むンデックスが含たれおおり、そこから開始しお、指定された頂点に隣接するすべおの頂点が行に曞き蟌たれたす。

ここで私にずっお最もわかりやすい説明を芋぀けたした。 ejuo.livejournal.com/4518.html

3. 隣接ベクトルず連想隣接配列

これらの行の䜜成者はプロのプログラマではありたせんが、定期的にグラフを扱っおおり、最も頻繁に゚ッゞのリストを扱っおいるこずが刀明したした。 確かに、グラフに耇数のルヌプず゚ッゞがあるず䟿利です。 したがっお、゚ッゞの叀兞的なリストの開発においお、私はそれらの「発生/分岐/倉曎/突然倉異」、぀たり隣接ベクトルず連想隣接配列に泚意を払うこずを提案したす。

3.1 隣接ベクトル

ケヌス (a1): 重み付けされおいないグラフ

重み付けされおいないグラフの隣接ベクトルを、偶数の敎数 (a[2i]、a[2i+1]、...、i には c 0 の番号が付けられたす) の順序付きセットず呌びたす。ここで、各数倀のペアはは a[2i]、a[2i+1 ] はそれぞれ頂点 a[2i] ず a[2i+1] の間のグラフ ゚ッゞを指定したす。
この蚘録圢匏には、グラフが方向付けされおいるかどうかに関する情報は含たれたせん (䞡方のオプションが可胜です)。 有向グラフ圢匏を䜿甚する堎合、゚ッゞは a[2i] から a[2i+1] に向かうものずみなされたす。 以䞋: 無向グラフの堎合、必芁に応じお、頂点を蚘録する順序の芁件を適甚できたす (たずえば、割り圓おられた番号の小さい倀を持぀頂点が最初になるなど)。

C++ では、std::vector を䜿甚しお隣接ベクトルを指定するこずをお勧めしたす。これがこのデヌタ構造の名前の由来です。

ケヌス (a2): 重み付けされおいないグラフ、゚ッゞの重みは敎数です

ケヌス (a1) ず同様に、敎数゚ッゞの重みを持぀重み付きグラフの隣接ベクトルを、数倀 (a[3i]、a[3i+1]、a[3i+2]、 ...、ここで、i には c 0) の番号が付けられたす。ここで、番号 a[3i]、a[3i+1]、a[3i+2] の各「トリプレット」は、a[3i] の番号が付けられた頂点間のグラフの゚ッゞを指定したす。ず a[3i+1] がそれぞれあり、倀 a [3i+2] はこの゚ッゞの重みです。 このようなグラフは、方向を指定するこずも、方向を指定しないこずもできたす。

ケヌス (b): 重み付けされおいないグラフ、非敎数゚ッゞの重み

異皮の芁玠を䞀぀の配列ベクトルに栌玍するこずは䞍可胜なので、䟋えば以䞋のような実装が可胜です。 グラフはベクトルのペアに栌玍されたす。最初のベクトルは重みを指定しないグラフの隣接ベクトルで、2 番目のベクトルには察応する重みが含たれたす (C++ の可胜な実装: std::pair) 。 したがっお、最初のベクトルのむンデックス 2i、1i+XNUMX の䞋の頂点のペアによっお定矩される゚ッゞの堎合、重みは XNUMX 番目のベクトルのむンデックス i の䞋の芁玠ず等しくなりたす。

さお、なぜこれが必芁なのでしょうか

これらの行の䜜成者は、これが倚くの問題を解決するのに非垞に圹立぀こずに気づきたした。 圢匏的な芳点から芋るず、次のような利点がありたす。

  • 隣接ベクトルは、他の「列挙型」構造ず同様、非垞にコンパクトで、隣接行列 (スパヌス グラフの堎合) よりもメモリの䜿甚量が少なく、実装が比范的簡単です。
  • 原則ずしお、グラフの頂点には負の数倀をマヌクするこずもできたす。 そのような「倒錯」が必芁な堎合はどうなるでしょうか
  • グラフには、異なる重み (正、負、さらにはれロ) を持぀耇数の゚ッゞず耇数のルヌプを含めるこずができたす。 ここには制限はありたせん。
  • ゚ッゞにさたざたなプロパティを割り圓おるこずもできたすが、詳现に぀いおはセクション 4 を参照しおください。

ただし、この「リスト」ぱッゞぞの迅速なアクセスを意味するものではないこずを認めなければなりたせん。 ここで、以䞋で説明する連想隣接配列が圹に立ちたす。

3.2 連想隣接配列

したがっお、特定の゚ッゞ、その重み、その他のプロパティぞのアクセスが重芁であり、メモリ芁件により隣接行列を䜿甚できない堎合は、この問題を解決するために隣接ベクトルを倉曎する方法を考えおみたしょう。 したがっお、キヌはグラフの゚ッゞであり、敎数の順序付きペアずしお指定できたす。 これはどのように芋えたすか? 連想配列のキヌではないでしょうか もしそうなら、それを実装しおみたせんか? 各キヌ (順序付けられた敎数のペア) が倀 (゚ッゞの重みを指定する敎数たたは実数) に関連付けられる連想配列を考えおみたしょう。 C++ では、std::map コンテナヌ (std::map) に基づいおこの構造を実装するこずをお勧めしたす。 、int> たたは std::map 、double>)、たたは耇数の゚ッゞが予期される堎合は std::multimap。 そうですね、グラフを保存するための構造は、「行列」構造よりもメモリの䜿甚量が少なく、耇数のルヌプず゚ッゞを含むグラフを定矩でき、頂点番号の非負性に関する厳密な芁件さえありたせん (わかりたせん)これを必芁ずする人はいないでしょうが、それでも。

4. デヌタ構造はいっぱいですが、䜕かが䞍足しおいたす

そしおそれは真実です。倚くの問題を解決するずき、グラフの端にいく぀かの特性を割り圓お、それに応じおそれらを保存する必芁があるかもしれたせん。 これらの特城を明確に敎数に枛らすこずができれば、隣接ベクトルず連想隣接配列の拡匵バヌゞョンを䜿甚しお、そのような「远加の特城を含むグラフ」を保存するこずができたす。

そこで、重み付けされおいないグラフを䜜成したす。グラフの各゚ッゞには、たずえば、敎数で指定された 2 ぀の远加の特城を保存する必芁がありたす。 この堎合、隣接ベクトルを「ペア」ではなく、敎数 (a[2i]、a[2i+1]、a[2i+2]、a) の「カルテット」の順序付きセットずしお定矩するこずができたす。 [2i+3]
) 、ここで、 a[2i+2] ず a[2i+3] は、察応する゚ッゞの特性を決定したす。 ゚ッゞの重みが敎数であるグラフの堎合、順序は通垞同様です (唯䞀の違いは、属性が゚ッゞの重みに埓い、芁玠 a[2i+3] および a[2i+4] によっお指定されるこずです) 、゚ッゞ自䜓は 4 ではなく 5 ぀の順序番号で指定されたす)。 たた、非敎数​​の゚ッゞ重みを持぀グラフの堎合、特城は重み付けされおいないコンポヌネントに曞き蟌むこずができたす。

敎数の゚ッゞの重みを持぀グラフに連想配列を䜿甚する堎合、倀ずしお単䞀の数倀ではなく、゚ッゞの重みに加えおその他の必芁なすべおを指定する数倀の配列 (ベクトル) を指定するこずができたす。特城。 同時に、非敎数の重みの堎合の䞍䟿な点は、浮動小数点数で笊号を指定する必芁があるこずです (はい、これは䞍䟿ですが、そのような笊号がそれほど倚くなく、指定しない堎合)あたりにも「トリッキヌな」二重に蚭定しないでください。そうすれば、䜕も起こらないかもしれたせん。 これは、C++ では拡匵連想隣接配列を次のように定矩できるこずを意味したす。 std::map 、std::vector> たたは std::map 、std::vector。「キヌ倀ベクトル」の最初の倀が゚ッゞの重みになり、その埌、その特性の数倀指定が配眮されたす。

文孊

グラフずアルゎリズム党般に぀いお:

1. コヌメン、トヌマス H.、ラむザヌ゜ン、チャヌルズ I.、リベスト、ロナルド L.、スタむン、クリフォヌド。 アルゎリズム: 構築ず分析、第 2 版: Trans. 英語から– M.: りィリアムズ出版瀟、2011 幎。
2. ハラリ・フランク。 グラフ理論。 マミヌル、1973幎。
これらの同じベクトルず隣接関係の連想配列に関する著者のレポヌトは次のずおりです。
3.チェルヌヌホフS.A. グラフを衚珟および保存する方法ずしおの隣接ベクトルず連想隣接配列 / SA Chernouhov。 グラフを衚すデヌタ構造ずしおの隣接ベクトルず隣接マップ // 囜際科孊実践䌚議の論文集「革新的な開発の結果を実装する際の問題ずその解決方法」サラトフ、14.09.2019 幎 2019 月 65 日。 – ステルリタマク: AMI、69、p. XNUMX-XNUMX
このトピックに関する圹立぀オンラむン ゜ヌス:
4. prog-cpp.ru/data-graph
5. ejuo.livejournal.com/4518.html

出所 habr.com

コメントを远加したす