Essa resposta não é apenas para C ++, pois tudo mencionado é sobre as estruturas de dados, independentemente da linguagem. E, minha resposta é assumir que você conhece a estrutura básica de listas e matrizes de adjacência.
Memória
Se a memória é sua principal preocupação, você pode seguir esta fórmula para um gráfico simples que permite loops:
Uma matriz de adjacência ocupa n 2 /8 Espaço de bytes (um bit por entrada).
Uma lista de adjacência ocupa espaço 8e, onde e é o número de arestas (computador de 32 bits).
Se definirmos a densidade do gráfico como d = e / n 2 (número de arestas dividido pelo número máximo de arestas), podemos encontrar o "ponto de interrupção" em que uma lista ocupa mais memória que uma matriz:
8e> n 2 /8 , quando d> 1/64
Portanto, com esses números (ainda específicos de 32 bits), o ponto de interrupção chega a 1/64 . Se a densidade (e / n 2 ) for maior que 1/64, será preferível uma matriz se você quiser economizar memória.
Você pode ler sobre isso na wikipedia (artigo sobre matrizes de adjacência) e em muitos outros sites.
Nota : Pode-se melhorar a eficiência de espaço da matriz de adjacência usando uma tabela de hash em que as chaves são pares de vértices (somente não direcionados).
Iteração e pesquisa
As listas de adjacências são uma maneira compacta de representar apenas as arestas existentes. No entanto, isso tem o custo de uma pesquisa possivelmente lenta de arestas específicas. Como cada lista possui o grau de um vértice, o pior caso de verificação de uma borda específica pode se tornar O (n), se a lista não estiver ordenada. No entanto, procurar os vizinhos de um vértice se torna trivial e, para um gráfico esparso ou pequeno, o custo de iterar pelas listas de adjacências pode ser insignificante.
As matrizes de adjacência, por outro lado, usam mais espaço para fornecer tempo de pesquisa constante. Como existe toda entrada possível, é possível verificar a existência de uma borda em tempo constante usando índices. No entanto, a pesquisa de vizinhos usa O (n), pois você precisa verificar todos os possíveis vizinhos. A desvantagem óbvia do espaço é que, para gráficos esparsos, muito preenchimento é adicionado. Veja a discussão sobre memória acima para obter mais informações sobre isso.
Se você ainda não tiver certeza do que usar : A maioria dos problemas do mundo real produz gráficos esparsos e / ou grandes, mais adequados para representações de listas de adjacências. Eles podem parecer mais difíceis de implementar, mas garanto que não. Quando você escreve um BFS ou DFS e deseja buscar todos os vizinhos de um nó, fica a apenas uma linha de código. No entanto, observe que não estou promovendo listas de adjacência em geral.