답변:
공간 효율성 만 신경 쓰면 압축 된 데이터 구조가 가장 좋을 것입니다. 물론 액세스 또는 업데이트에는 그다지 효율적이지 않습니다 .....
그래프에 상대적으로 적은 수의 노드가 있고 상당히 조밀 한 경우 (모든 가능한 연결의 5 % 이상이 존재 함) 에지 목록을 사용하는 것보다 인접 행렬 을 만드는 것이 더 공간 효율적일 수 있습니다 . 이것은 가능한 (지정된) 연결 당 단 하나의 비트 만 필요하며 n * n 비트는 n 개의 노드가있는 경우 총계입니다.
그렇지 않으면 인접 링크를 사용해야하는 경우 링크 당 하나의 참조보다 쉽게 수행 할 수 없습니다. 이는 링크에 저장해야하는 최소 정보 내용이기 때문입니다. 뒤로 링크를 원하면 링크 수의 두 배가 필요합니다.
이것 위에 시도 할 수있는 몇 가지 트릭이 있습니다. 예를 들어, 링크의 서브 세트를 공유 할 수 있습니다 (A와 B가 각각 C, D, E를 참조하는 경우 링크 C, D, E를 한 번만 저장하십시오 .....). 그러나 이것은 매우 빨리 복잡해지며 대부분의 경우 노력할 가치가 있다고 생각합니다.
또 다른 트릭-그래프에 합리적인 수의 노드가 있다고 가정하면 전체 포인터 / 참조 대신 16 비트 노드 인덱스 번호를 사용하여 인덱싱하여 공간을 절약 할 수 있습니다.
데이터 구조에 따라 달라집니다.
방향이 지정되지 않은 가장자리가있는 고밀도 그래프의 경우 실제로 삼각 행렬을 나타내는 비트 배열 목록을 이길 수 없습니다. List<BitArray>
예를 들어. 논리적으로 다음과 같습니다.
0123
0
11
211
3001
41010
여기에서 루트 BitArray의 색인을 사용하여 노드 데이터를 저장하는 목록으로 색인을 작성할 수 있습니다.
예를 들어, 노드의 모든 이웃을 얻는 것은 다음과 같습니다.
// C#
List<Node> Nodes = /* populated elsewhere */
List<BitArray> bits = /* populated elsewhere */
public static IEnumerable<Node> GetNeighbours(int x)
{
for (int i = 0; i < bits[idx].Count; i++)
{
if (this.bits[idx][i])
yield return this.Nodes[i];
}
for (int i = 0; i < this.Nodes.Count; i++)
{
if (idx < this.bits[i].Count && this.bits[i][idx])
yield return this.Nodes[i];
}
}
(데이터의 양에 따라 인덱스 유형을 바이트 또는 ushort 또는 모든 행이 양수이므로 해당 행을 따라 선택할 수 있습니다. 사소한 것이므로 이것을 미세 최적화로 간주하지 않습니다)
유 방향 그래프의 경우, 인접 인덱스 목록으로 이동할 수있는 노드 수에 비해 매우 드문 경우가 아니라면 연결을 저장하기 위해 * n 비트 배열의 경로로 이동합니다.