Je pense que votre premier exemple est un peu ambigu: les nœuds comme objets et les arêtes comme pointeurs. Vous pouvez garder une trace de ceux-ci en stockant uniquement un pointeur vers un nœud racine, auquel cas accéder à un nœud donné peut être inefficace (disons que vous voulez le nœud 4 - si l'objet nœud n'est pas fourni, vous devrez peut-être le rechercher) . Dans ce cas, vous perdriez également des parties du graphique qui ne sont pas accessibles depuis le nœud racine. Je pense que c'est le cas que f64 rainbow suppose quand il dit que la complexité en temps pour accéder à un nœud donné est O (n).
Sinon, vous pouvez également conserver un tableau (ou hashmap) plein de pointeurs vers chaque nœud. Cela permet à O (1) d'accéder à un nœud donné, mais augmente un peu l'utilisation de la mémoire. Si n est le nombre de nœuds et e est le nombre d'arêtes, la complexité spatiale de cette approche serait O (n + e).
La complexité spatiale pour l'approche matricielle serait le long des lignes de O (n ^ 2) (en supposant que les arêtes sont unidirectionnelles). Si votre graphique est clairsemé, vous aurez beaucoup de cellules vides dans votre matrice. Mais si votre graphe est entièrement connecté (e = n ^ 2), cela se compare favorablement à la première approche. Comme le dit RG, vous pouvez également avoir moins d'erreurs de cache avec cette approche si vous allouez la matrice comme un morceau de mémoire, ce qui pourrait accélérer le suivi de beaucoup d'arêtes autour du graphique.
La troisième approche est probablement la plus efficace en termes d'espace dans la plupart des cas - O (e) - mais ferait de la recherche de tous les bords d'un nœud donné une tâche O (e). Je ne peux pas penser à un cas où cela serait très utile.