Penso che il tuo primo esempio sia un po 'ambiguo: nodi come oggetti e bordi come puntatori. Puoi tenerne traccia memorizzando solo un puntatore a qualche nodo radice, nel qual caso l'accesso a un dato nodo potrebbe essere inefficiente (supponiamo che tu voglia il nodo 4 - se l'oggetto nodo non è fornito, potresti doverlo cercare) . In questo caso, perderai anche porzioni del grafico che non sono raggiungibili dal nodo radice. Penso che questo sia il caso che f64 rainbow assume quando dice che la complessità temporale per accedere a un dato nodo è O (n).
Altrimenti, potresti anche mantenere un array (o hashmap) pieno di puntatori a ciascun nodo. Ciò consente a O (1) di accedere a un dato nodo, ma aumenta leggermente l'utilizzo della memoria. Se n è il numero di nodi ed e è il numero di archi, la complessità spaziale di questo approccio sarebbe O (n + e).
La complessità spaziale per l'approccio a matrice sarebbe lungo le linee di O (n ^ 2) (supponendo che gli archi siano unidirezionali). Se il tuo grafico è scarso, avrai molte celle vuote nella tua matrice. Ma se il tuo grafico è completamente connesso (e = n ^ 2), questo si confronta favorevolmente con il primo approccio. Come dice RG, potresti anche avere meno cache miss con questo approccio se allochi la matrice come un blocco di memoria, il che potrebbe rendere più veloce il seguire molti bordi attorno al grafico.
Il terzo approccio è probabilmente il più efficiente in termini di spazio per la maggior parte dei casi - O (e) - ma renderebbe la ricerca di tutti i bordi di un dato nodo un compito O (e). Non riesco a pensare a un caso in cui questo sarebbe molto utile.