그래프는 노드vertex
와 간선edge
을 이용한 비선형 데이터 구조이다. 보통 그래프는 데이터 간 관계를 표현하는 데 사용한다.
여기서 간선은 방향이 있을 수도 있고 없을 수도 있다. 만약에 관계나 흐름에서 정도를 표현할 필요가 있다면 가중치라는 개념을 추가하여 표현한다.
예를 들어 도시 간 인구 이동을 그래프로 표현하면 다음과 같다.
노드에는 어떤 데이터가 들어있다. 그리고 노드 사이에 있는 것이 간선이다. 인구 이동의 경우 어디서 얼마나 이동했는지 표시해야 하므로 간선에 가중치를 표현했다.
방향 그래프Directed Graph
: 방향이 있는 간선을 포함한다. A에서 B로만 갈 수 있는 것과 B에서 A로만 갈 수 있는 것을 구분한다.
무방향 그래프Undirected Graph
: 간선에 방향이 없어 A와 B가 서로를 연결하는 것으로 취급한다.
이때, 방향 그래프는 어느 한쪽으로만 간선이 있는 것이 아니라 정점이 서로를 가리키는 형태의 간선이 있을 수도 있다.
Weighted Graph
: 간선에 가중치가 할당된 그래프이다. 예를 들어, 도로망에서 각 도로가 가지는 거리나 비용을 나타내는 경우 등에 사용된다.순환 그래프Cycle Graph
: 특정 노드에서 시작해 간선을 따라 다시 돌아오는 경로가 있는 그래프
비순환 그래프Acyclic Graph
: 순환이 존재하지 않는 그래프
앞서 언급했듯 특정 노드에서 시작해 간선을 따라 다시 돌아오면 순환 그래프이다. 예시의 경우 2 -> 4 -> 3 -> 2이므로 그래프의 일부분이 순환된다. 1,2,3은 모두 연결되어 있긴 하지만 순환하진 않는다.
예를 들어 서울에서 부산으로 유동 인구가 8,000명 발생했다와 같은 내용을 그래프로 표현한다고 해보자. 그래프의 노드, 간선, 방향, 가중치와 문장의 의미를 이렇게 연결하여 정리할 수 있다.
그래프의 구현 방시에는 인접 행렬adjacency matrix
와 인접 리스트adjacency list
가 있다. 두 방법으로 구현해보자.
인접 행렬은 배열을 활용하여 구현하는 경우가 많다.
인접 행렬로 표현하면 세로 방향 인덱스를 출발, 가로 방향 인덱스를 도착으로 하니 서울(0) -> 부산(1)
으로 향하는 가중치가 400km
인 그래프가 표현되었다. 그리고 -로 표현한 가중치는 실제 코드에서는 굉장히 큰 값을 넣거나 -1
로 정한다.
인접 리스트로 그래프를 표현하려면 우선 다음과 같이 적절한 노드를 정의해야 한다. 그림에서 보듯 값v
, 가중치w
, 다음 노드next
를 묶어 관리한다.
노드 개수만큼 배열 준비: 각 정점마다 인접한 정점들을 연결 리스트LinkedList
로 표현할 배열을 준비한다.
배열의 인덱스는 각 시작 노드를 의미: 배열의 인덱스는 각 정점을 나타낸다. 예를 들어, 인덱스 0은 정점 A를 나타내고, 인덱스 1은 정점 B를 나타낸다.
인접 리스트 구성: 각 정점마다 연결된 다른 정점들을 연결리스트로 관리한다. 연결 리스트의 각 노드는 연결된 정점의 정보를 가지고 있다.
1 -> 2
(가중치 3) 표현2 -> 1
(가중치 6) 표현
2 -> 3
(가중치 5) 표현
여기서 이미 배열에는 노드 2가 연결되어 있기 때문에, 다음 노드가 NULL
인 노드를 찾아 2 -> 3
(가중치 5)를 표현한 노드를 연결한다.
O(1)
array[2][93]
에 가중치가 있는지만 확인하면 된다.N X N
) 비효율적1,2,3,999
와 같이 간격이 크면 가장 큰 노드의 값인 999
를 기준으로 인접 행렬의 크기를 잡아야 함💡 희소 그래프란?
노드 수에 비해 간선 수가 매우 적은 그래프를 말한다.
O(N)
O(N)
이 된다.표로 정리한 인접 행렬과 인접 리스트의 장단점은 다음과 같다.
특성 | 메모리 사용 | 탐색 시간 | 구현 난이도 |
---|---|---|---|
인접 행렬 | O(N²) | O(1) | 낮음 |
인접 리스트 | O(N³) | O(N) | 높음 |
그래프 문제를 풀 때는 더 좋은 것을 선택해야 하지만 보통은 시간 제약에서 장점을 취하기 위해 인정 행렬 방식으로 그래프 문제를 푸는 경우가 많다. **문제에서 노드 개수가 1,000개 미만으로 주어지는 경우에는 인접 행렬을 사용하면 된다.
💡 노드의 데이터가 숫자가 아닌 문자열이면, 문자열을 숫자로 매핑하여 인접 행렬의 인덱스로 사용하면 된다.