Ich denke, Ihr erstes Beispiel ist etwas mehrdeutig - Knoten als Objekte und Kanten als Zeiger. Sie können diese verfolgen, indem Sie nur einen Zeiger auf einen Stammknoten speichern. In diesem Fall ist der Zugriff auf einen bestimmten Knoten möglicherweise ineffizient (beispielsweise möchten Sie Knoten 4 - wenn das Knotenobjekt nicht bereitgestellt wird, müssen Sie möglicherweise danach suchen). . In diesem Fall verlieren Sie auch Teile des Diagramms, die vom Stammknoten aus nicht erreichbar sind. Ich denke, dies ist der Fall, den f64 rainbow annimmt, wenn er sagt, dass die zeitliche Komplexität für den Zugriff auf einen bestimmten Knoten O (n) ist.
Andernfalls können Sie auch ein Array (oder eine Hashmap) voller Zeiger auf jeden Knoten behalten. Dies ermöglicht O (1) den Zugriff auf einen bestimmten Knoten, erhöht jedoch die Speichernutzung ein wenig. Wenn n die Anzahl der Knoten und e die Anzahl der Kanten ist, wäre die Raumkomplexität dieses Ansatzes O (n + e).
Die Raumkomplexität für den Matrixansatz würde entlang der Linien von O (n ^ 2) liegen (vorausgesetzt, die Kanten sind unidirektional). Wenn Ihr Diagramm spärlich ist, haben Sie viele leere Zellen in Ihrer Matrix. Wenn Ihr Graph jedoch vollständig verbunden ist (e = n ^ 2), ist dies im Vergleich zum ersten Ansatz günstig. Wie RG sagt, kann es bei diesem Ansatz auch zu weniger Cache-Fehlern kommen, wenn Sie die Matrix als einen Speicherblock zuweisen, wodurch das Verfolgen vieler Kanten im Diagramm schneller werden kann.
Der dritte Ansatz ist in den meisten Fällen wahrscheinlich der platzsparendste - O (e) -, würde jedoch das Finden aller Kanten eines bestimmten Knotens zu einer O (e) -Aufgabe machen. Ich kann mir keinen Fall vorstellen, in dem dies sehr nützlich wäre.