그래프 데이터 구조를 구현하는 가장 공간 효율적인 방법은 무엇입니까?


14

나는 일반적으로 그래프를 이중 연결 목록으로 구현하지만 k 이웃에 대한 k 포인터 / 참조가 필요하기 때문에 경험상 상당히 공간 비효율적입니다. 그래서 무 방향 그래프의 경우 수학 내에서 올바른 경우 2k 개의 이웃 링크를 갖습니다. 공간을 절약하는 더 좋은 방법이 있습니까? 그래프가 지시되면 일부 링크를 단일로 만들 수 있지만 더 나은 작업을 수행 할 수있는 방법이 있습니까?

답변:


12

공간 효율성 만 신경 쓰면 압축 된 데이터 구조가 가장 좋을 것입니다. 물론 액세스 또는 업데이트에는 그다지 효율적이지 않습니다 .....

그래프에 상대적으로 적은 수의 노드가 있고 상당히 조밀 한 경우 (모든 가능한 연결의 5 % 이상이 존재 함) 에지 목록을 사용하는 것보다 인접 행렬 을 만드는 것이 더 공간 효율적일 수 있습니다 . 이것은 가능한 (지정된) 연결 당 단 하나의 비트 만 필요하며 n * n 비트는 n 개의 노드가있는 경우 총계입니다.

그렇지 않으면 인접 링크를 사용해야하는 경우 링크 당 하나의 참조보다 쉽게 ​​수행 할 수 없습니다. 이는 링크에 저장해야하는 최소 정보 내용이기 때문입니다. 뒤로 링크를 원하면 링크 수의 두 배가 필요합니다.

이것 위에 시도 할 수있는 몇 가지 트릭이 있습니다. 예를 들어, 링크의 서브 세트를 공유 할 수 있습니다 (A와 B가 각각 C, D, E를 참조하는 경우 링크 C, D, E를 한 번만 저장하십시오 .....). 그러나 이것은 매우 빨리 복잡해지며 대부분의 경우 노력할 가치가 있다고 생각합니다.

또 다른 트릭-그래프에 합리적인 수의 노드가 있다고 가정하면 전체 포인터 / 참조 대신 16 비트 노드 인덱스 번호를 사용하여 인덱싱하여 공간을 절약 할 수 있습니다.


모든 링크가 방향이 지정되지 않은 경우 에지를 낮은 노드에서 높은 노드로 저장하여 공간의 절반 만 절약 할 수 있습니다.
중복 제거기

6

데이터 구조에 따라 달라집니다.

방향이 지정되지 않은 가장자리가있는 고밀도 그래프의 경우 실제로 삼각 행렬을 나타내는 비트 배열 목록을 이길 수 없습니다. 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 비트 배열의 경로로 이동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.