객체 그래프 표현을 인접 목록 및 행렬 표현과 비교


81

현재 기술 프로그래밍 인터뷰 준비에 대한 Steve Yegge의 조언을 따르고 있습니다. http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html

그래프에 대한 그의 섹션에서 그는 다음과 같이 말합니다.

메모리에서 그래프를 표현하는 세 가지 기본 방법 (객체 및 포인터, 행렬 및 인접 목록)이 있으며 각 표현과 장단점을 숙지해야합니다.

행렬 및 인접 목록 표현의 장단점은 CLRS에 설명되어 있지만이를 객체 표현과 비교하는 리소스를 찾을 수 없었습니다.

그것에 대해 생각하는 것만으로도 이것의 일부를 직접 추론 할 수 있지만 중요한 것을 놓치지 않았는지 확인하고 싶습니다. 누군가 이것을 포괄적으로 설명하거나 그렇게하는 자료를 알려줄 수 있다면 대단히 감사하겠습니다.


방법에 대한 유도 그래프 - 아래이 가을을 3 종류의?
Erik Kaplun

답변:


94

개체 및 포인터

이것들은 다른 답변에서 말한 hammar와 같은 기본 데이터 구조 Java입니다.이를 가장자리 및 정점과 같은 클래스로 표현할 수 있습니다. 예를 들어 가장자리는 두 개의 정점을 연결하고 방향을 지정하거나 지정하지 않을 수 있으며 가중치를 포함 할 수 있습니다. 정점은 ID, 이름 등을 가질 수 있습니다. 대부분 둘 다 추가 속성이 있습니다. 따라서 다음과 같이 그래프를 구성 할 수 있습니다.

Vertex a = new Vertex(1);
Vertex b = new Vertex(2);
Edge edge = new Edge(a,b, 30); // init an edge between ab and be with weight 30  

이 접근 방식은 객체 지향 사용자에게 더 읽기 쉽고 편리하기 때문에 객체 지향 구현에 일반적으로 사용됩니다.

매트릭스

행렬은 단순한 2 차원 배열입니다. 다음과 같이 int 배열로 나타낼 수있는 정점 ID가 있다고 가정합니다.

int[][] adjacencyMatrix = new int[SIZE][SIZE]; // SIZE is the number of vertices in our graph
adjacencyMatrix[0][1] = 30; // sets the weight of a vertex 0 that is adjacent to vertex 1

일반적으로 인덱스 액세스가 필요한 조밀 한 그래프에 사용됩니다. 이것으로 무 / 방향 및 가중치 구조를 나타낼 수 있습니다.

인접 목록

이것은 단순한 데이터 구조 혼합이며, 일반적으로 HashMap<Vertex, List<Vertex>>. 유사하게 HashMultimap구아바에서 사용할 수 있습니다 .

O (1) (상각 된) 정점 조회가 있고 내가 요구 한 특정 정점에 인접한 모든 정점의 목록을 반환하기 때문에이 접근 방식은 멋집니다.

ArrayList<Vertex> list = new ArrayList<>();
list.add(new Vertex(2));
list.add(new Vertex(3));
map.put(new Vertex(1), list); // vertex 1 is adjacent to 2 and 3

이것은 희소 그래프를 나타내는 데 사용됩니다. Google에 지원하는 경우 웹 그래프가 희소하다는 것을 알아야합니다. BigTable을 사용하여보다 확장 가능한 방식으로 처리 할 수 ​​있습니다 .

아 그리고 BTW, 여기 에 멋진 사진과 함께이 게시물의 아주 좋은 요약이 있습니다.)


이 접근 방식은 멋지다. 왜냐하면 O (1) 정점 조회가 있기 때문에이 복잡성은 약간 잘못되었습니다. 특히 알파 = 해시 맵의 슬롯 수 / 정점 수인 O (1 + alpha)입니다. 따라서 해시 맵 대신 배열을 사용하도록 제안합니다
Timofey 2013 년

@Tim 그것은 O (1) 상각입니다. 복잡성 계산은 구현에 따라 크게 달라집니다. HashMap( docs.oracle.com/javase/7/docs/api/java/util/HashMap.html ) 의 javadoc을 참조하십시오 . This implementation provides constant-time performance for the basic operations= O (1) 상각.
Thomas Jungblut 2013 년

6
@Tim 여기있는 모든 사람들이 어레이 액세스가 어떤 HashTable사용 보다 빠르다는 것을 알고 있다고 생각 합니다. 따라서 무시할 수있는 작은 상수 알파 오버 헤드로 arround를 nitpick 할 필요가 없습니다.
Thomas Jungblut 2013 년

2
날 오해하지 마십시오, 왜 :) 여기 말할 것도없고 나는 당신에게 좋은 대답을 불쾌하게하지 않습니다,하지만 난 당신의 대답은 개선 될 수 있다는 느낌이
Timofey

2
@Tim 나는 대답에 상각 된 메모를 추가했습니다. 감사.
Thomas Jungblut 2013 년

7

객체와 포인터는 적어도 이러한 표현을 사용하는 알고리즘을 비교하기 위해 인접 목록과 거의 동일합니다.

비교

struct Node {
    Node *neighbours[];
};

struct Node {
    Node *left;
    Node *right;
};

명명 된 포인터보다 작업하는 것이 더 쉬운 경우 후자의 경우 즉시 이웃 목록을 쉽게 구성 할 수 있습니다.


4

객체 표현 ( incidence list ) 의 장점은 인접한 두 정점이 가장자리의 동일한 인스턴스를 공유한다는 것입니다. 따라서 방향이 지정되지 않은 에지 데이터 (길이, 비용, 흐름 또는 방향)로 쉽게 조작 할 수 있습니다. 그러나 포인터에 추가 메모리를 사용합니다.


5
"발생 목록"이라는 이름의 인접 목록 표현에 대한 링크가있는 이유는 무엇입니까? 아마이 하나를 사용하는 것이 좋습니다 algorithmist.com/index.php/Graph_data_structures#Incidence_List
Timofey

1

또 다른 좋은 리소스 : Khan Academy- "그래프 표현"

인접 목록 및 인접 행렬 외에도 세 번째 유형의 그래프 표현으로 "가장자리 목록"을 나열합니다. 에지 목록은 Thomas의 "객체 및 포인터"답변과 같은 "가장자리 객체"목록으로 해석 될 수 있습니다.

장점 : Edge에 대한 더 많은 정보를 저장할 수 있습니다 (Michal이 언급 함).

단점 : 작업하기에 매우 느린 데이터 구조입니다.

  • 모서리 조회 : O (log e)
  • 가장자리 제거 : O (e)
  • 주어진 노드에 인접한 모든 노드 찾기 : O (e)
  • 두 노드 사이에 경로가 있는지 확인 : O (e ^ 2)

e = 모서리 수

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