Adjazenzliste und Matrixdarstellung des Diagramms

⚡ Intelligente Zusammenfassung

Adjazenzlisten und Adjazenzmatrizen speichern Knoten und Kanten im Speicher und ermöglichen so das Durchlaufen von Netzwerken. Adjazenzlisten verwenden verkettete Listen pro Knoten, während Adjazenzmatrizen ein quadratisches zweidimensionales Gitter nutzen.

  • 📐 Nachbarschaftsliste: Ein Array von V verketteten Listen, wobei jede Liste am Index i jeden zu Knoten i benachbarten Knoten speichert, was einen Speicherbedarf von O(V + E) ergibt.
  • 🗺️ Adjazenzmatrix: AV × V zweidimensionales Array, wobei matrix[i][j] das Kantengewicht enthält oder 1, wenn eine Kante zwischen Knoten i und Knoten j existiert.
  • ⚡ Suchgeschwindigkeit: Die Adjazenzmatrix beantwortet die Frage „Gibt es eine Kante zwischen i und j?“ in O(1) Zeit, während die Adjazenzliste O(Grad) Zeit benötigt, um die Nachbarliste zu durchsuchen.
  • 💾 Erinnerung: Eine Adjazenzmatrix benötigt selbst bei dünn besetzten Graphen immer O(V²) Speicherplatz, wohingegen eine Adjazenzliste mit der tatsächlichen Kantenanzahl skaliert.
  • 🔍 beste Passform: Wählen Sie die Adjazenzmatrix für dichte Graphen mit häufigen Kantenabfragen und die Adjazenzliste für dünn besetzte Graphen und rechenintensive Arbeitslasten.
  • ️ Anwendungen: Beide Darstellungsformen bilden die Grundlage für BFS, DFS, Dijkstra, PageRank, Routing in Straßennetzen und Graph-Neuronale-Netzwerk-Pipelines, die in KI-Systemen eingesetzt werden.

Adjazenzliste und Matrixdarstellung des Diagramms

Auch wenn sie alle unterschiedlich aussehen Arten von Diagrammen kann auf ähnliche Weise dargestellt werden. Es gibt im Allgemeinen zwei Arten der grafischen Darstellung:

  1. Adjazenzmatrix
  2. Adjazenzliste

Adjazenzliste

Eine Adjazenzliste besteht aus verketteten Listen. Jeder Knoten wird als Array-Index betrachtet, und jedes Element repräsentiert eine verkettete Liste. Diese verketteten Listen enthalten die Knoten, die eine Kante mit dem Indexknoten gemeinsam haben.

Hier ist ein Beispiel für eine Adjazenzliste:

Adjazenzliste

Gegeben sei ein Graph mit V Knoten und E Kanten. Die Speicherkomplexität der Adjazenzliste beträgt O(V + E), das mit der Anzahl der tatsächlichen Kanten skaliert und nicht mit jedem möglichen Paar von Knoten.

Die Speicherkomplexität im ungünstigsten Fall wird O(V²) Wenn der gegebene Graph ein vollständiger Graph ist, dann ist jeder Knoten mit jedem anderen Knoten verbunden.

Adjazenzmatrix

Eine Adjazenzmatrix besteht aus einem zweidimensionalen Array. Für einen Graphen mit V Knoten beträgt die Größe der Matrix V × V.

Sagen matrix[i][j] = 5Das bedeutet, dass es eine Kante zwischen Knoten i und Knoten j gibt, deren Gewicht 5 beträgt.

Betrachten wir den folgenden Graphen und seine Adjazenzmatrix:

Adjazenzmatrix

Wir haben das gebaut 2D-Array mit diesen Schritten:

Schritt 1) Knoten A hat eine direkte Kante zu B, und das Gewicht beträgt 5. Daher wird die Zelle in Zeile A und Spalte B mit 5 gefüllt. Die restlichen Zellen in Zeile A werden mit Null gefüllt.

Schritt 2) Knoten B hat eine direkte Kante zu C, und die Kante hat das Gewicht 4. Daher wird die Zelle in Zeile B und Spalte C mit 4 gefüllt. Die restlichen Zellen in Zeile B werden mit Null gefüllt, da B keine ausgehende Kante zu einem anderen Knoten hat.

Schritt 3) Knoten C hat keine direkten Kanten zu anderen Knoten. Daher wird Zeile C mit Nullen gefüllt.

Schritt 4) Knoten D besitzt eine gerichtete Kante mit A und C.

  • Die Zelle in Zeile D und Spalte A hat den Wert 7. Die Zelle in Zeile D und Spalte C hat den Wert 2.
  • Die restlichen Zellen in Zeile D werden mit Nullen gefüllt.

Schritt 5) Knoten E hat eine gerichtete Kante mit B und D. Die Zelle in Zeile E und Spalte B hat den Wert 6. Die Zelle in Zeile E und Spalte D hat den Wert 3. Die restlichen Zellen in Zeile E werden mit Nullen aufgefüllt.

Hier sind einige Punkte, die Sie beachten sollten:

  • Der Graph hat keine Selbstschleifen, wenn die Hauptdiagonale der Adjazenzmatrix 0 ist.
  • Ein Graph ist gerichtet, wenn die Zellen an den Stellen (a, b) und (b, a) nicht denselben Wert haben. Andernfalls ist der Graph ungerichtet.
  • Es handelt sich um einen gewichteten Graphen, wenn der Wert einer beliebigen Zelle größer als 1 ist.

Das Hauptproblem der Adjazenzmatrix besteht darin, dass sie quadratischen Speicherplatz benötigt. Selbst nicht existierende Kanten belegen Speicherzellen.

Wenn wir beispielsweise einen Graphen mit 100 Knoten haben, benötigen wir 10,000 Zellen, um ihn zu speichern. RAMBei weniger Kanten im Graphen kann die Zuweisung so großen Speicherplatzes ineffizient sein. Daher beträgt die Speicherkomplexität unter Verwendung der Adjazenzmatrix O(N²), wobei N die Anzahl der Knoten im Graphen ist.

Adjazenzliste vs. Adjazenzmatrix

Vor der Auswahl einer Darstellungsform ist es hilfreich, beide Modelle anhand der Operationen, die bei realen Graph-Workloads dominieren, direkt miteinander zu vergleichen:

ProduktionAdjazenzmatrixAdjazenzliste
RaumkomplexitätO(V²)O(V + E)
Fügen Sie einen Scheitelpunkt hinzuO(V²)O (1)
Füge eine Kante hinzuO (1)O (1)
Eine Kante entfernenO (1)O(E)
Prüfen Sie, ob die Kante (i, j) existiertO (1)O(Grad von i)
Iteriere über die Nachbarn von iO (V)O(Grad von i)
am besten fürDichte Graphen, häufige KantenabfragenDünnbesetzte Graphen, traversierungsintensive Aufgaben

Kurz gesagt, die Adjazenzmatrix ist bei Kantenzugriffen mit konstanter Zeit im Vorteil, während die Adjazenzliste bei Speicherbedarf und Nachbariteration punktet. Aus diesem Grund werden Algorithmen wie BFS, DFS und Dijkstra üblicherweise mit Adjazenzlisten kombiniert.

Vor- und Nachteile der Graphdarstellung

Jede Darstellungsform hat ihre Vor- und Nachteile. Kennt man die Stärken und Schwächen beider Modelle, kann man das richtige für das jeweilige Problem auswählen.

Vorteile der Adjazenzmatrix:

  • Kantenexistenzabfragen mit konstanter Laufzeit O(1) zwischen beliebigen Knotenpaaren.
  • Die feste Indizierung erleichtert die Implementierung matrixbasierter Algorithmen wie Floyd-Warshall und transitiver Hülle.
  • Gewichtete Kanten passen natürlich in eine einzelne Matrixzelle.

Nachteile der Adjazenzmatrix:

  • Verschwendet O(V²) Speicherplatz, wenn der Graph dünn besetzt ist.
  • Das Hinzufügen eines neuen Knotens erfordert eine Größenänderung der gesamten Matrix.
  • Das Iterieren über die Nachbarn eines einzelnen Knotens benötigt O(V), selbst wenn der Knoten nur wenige Kanten hat.

Vorteile der Adjazenzliste:

  • Benötigt nur O(V + E) Speicherplatz, was nahe an der tatsächlichen Kantenanzahl in dünn besetzten Graphen liegt.
  • Das Hinzufügen eines neuen Knotens oder einer neuen Kante ist O(1).
  • Traversierungsalgorithmen wie BFS und DFS iterieren Nachbarn in O(Grad), was eine Gesamtlaufzeit von O(V + E) ergibt.

Nachteile der Adjazenzliste:

  • Die Überprüfung, ob eine bestimmte Kante existiert, benötigt O(Grad) Zeit anstatt O(1).
  • Die Cache-Lokalität ist schwächer, weil verkettete Listen über den gesamten Speicher verteilt sind.
  • Gewichtete Kanten benötigen ein Begleitfeld oder eine Liste von Paaren, was die Datenstruktur etwas komplizierter macht.

Wann verwendet man eine Adjazenzliste und wann eine Adjazenzmatrix?

Die Wahl der Darstellungsform hängt von der Dichte des Graphen und den am häufigsten ausgeführten Operationen ab. Nutzen Sie diese Kurzanleitung, um die richtige Struktur auszuwählen:

  • Die Adjazenzmatrix ist vorzuziehen. wenn der Graph dicht ist (E ist nahe an V²), wenn sich Kanten selten ändern und wenn Ihr Algorithmus viele Male fragt: „Gibt es eine Kante zwischen i und j?“
  • Bevorzugen Sie die Adjazenzliste. wenn der Graph dünn besetzt ist (E ist viel kleiner als V²), wenn die Knoten- oder Kantenmenge während der Ausführung wächst und wenn Sie den Graphen mit BFS, DFS oder durchlaufen Dijkstras Algorithmus für kürzeste Wege.
  • Bevorzuge ein gemischtes Modell (Adjazenzliste plus Hash-Set von Kanten), wenn Sie sowohl eine schnelle Nachbariteration als auch O(1) Kantenabfragen benötigen, allerdings auf Kosten von zusätzlichem Speicherplatz.

Moderne Graphbibliotheken wie NetworkX und igraph verwenden standardmäßig Adjazenzlisten, da die meisten realen Graphen – soziale Netzwerke, Straßenkarten, Webseiten, Paketabhängigkeiten – dünn besetzt und traversierungsintensiv sind.

Häufig gestellte Fragen

Eine Adjazenzliste ist ein Array von V verketteten Listen, wobei jede Liste am Index i alle zu Knoten i benachbarten Knoten speichert. Der Speicherbedarf beträgt O(V + E), was für dünnbesetzte Graphen und Traversierungsalgorithmen wie BFS und DFS geeignet ist.

Eine Adjazenzmatrix ist ein zweidimensionales V × V-Array, wobei matrix[i][j] das Kantengewicht speichert oder 1, falls eine Kante zwischen Knoten i und Knoten j existiert. Die Kantensuche erfolgt in O(1), der Speicherbedarf ist jedoch stets O(V²).

Die Adjazenzmatrix beantwortet Kantenexistenzanfragen in konstanter Zeit (O(1)). Die Adjazenzliste iteriert Nachbarn in konstanter Zeit (O(Grad)), was für Traversierungsalgorithmen wie BFS, DFS und Dijkstra schneller ist. Die optimale Wahl hängt von den Operationen ab, die Ihre Arbeitslast dominieren.

Verwenden Sie eine Adjazenzliste, wenn der Graph dünn besetzt ist, sich Knoten und Kanten während der Ausführung ändern und der Algorithmus häufig benachbarte Knoten durchläuft. Soziale Netzwerke, Straßenkarten und Webseitengraphen erfüllen dieses Profil.

Eine Adjazenzmatrix eignet sich, wenn der Graph dicht ist, die Knotenmenge feststeht und der Algorithmus dieselbe Kante wiederholt abfragt. Der Floyd-Warshall-Test und die transitive Hülle lassen sich beide auf Adjazenzmatrizen anwenden.

Ja. Bei gerichteten Graphen ist die Matrix nicht symmetrisch, und die Liste speichert nur ausgehende Nachbarn. Bei gewichteten Graphen enthält die Matrixzelle das Gewicht, während die Liste Paare aus Nachbar und Gewicht speichert.

Graph-Neuronale Netze speisen Adjazenzmatrizen oder dünnbesetzte Kantentensoren in maschinelle Lernschichten ein, um Betrug zu erkennen, Moleküleigenschaften vorherzusagen und Empfehlungssysteme zu entwickeln. Wissensgraphen nutzen ebenfalls Adjazenzlisten-Kodierungen für KI-gestützte Suchvorgänge.

Ja. GitHub Copilot und ChatGPT generieren Adjazenzlisten- und Matrix-Boilerplate-Code für Python, C++ und JavaDie Entwickler müssen weiterhin Grenzfälle wie doppelte Kanten, Selbstschleifen und die korrekte Behandlung gerichteter oder gewichteter Graphen überprüfen.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: