위상 정렬(Topological Sort)
위상 정렬은 순서가 정해져 있는 작업을 차례로 수행해야 할 때 그 순서를 결정해주기 위해 사용하는 알고리즘이다.
즉, 방향 그래프에 존재하는 각 정점들의 선행 순서를 위배하지 않으면서 모든 정점을 나열하는 것 이다.
위상 정렬을 가장 잘 설명할 수 있는 예시는 대학의 선수과목 구조 또는 게임에서의 스킬트리 중 선행스킬이 존재하는 경우이다.
앞선 대표 예 두가지 중 각자 더 이해가 쉬운 예시를 떠올려 보면 쉽게 이해할 수 있을 것이다.
위상 정렬이 성립하기 위해서는 반드시 그래프에 순환이 존재하지 않아야 한다. 즉, 비순환 방향 그래프(Directed Acyclic Graph, DAG) 여야 한다. 그리고 하나의 방향 그래프에 대해서 위상 정렬을 수행한 결과 값이 여러개가 나올 수 있다.
위상 정렬 (Java)
import java.util.*;
public class TopologicalSort {
// 노드의 개수(v), 그래프 간선의 개수 (e)
public static int v;
// 모든 노드에 대한 진입차수를 기록할 배열
public static int[] indegree;
// 각 노드에 연결된 간선 정보를 담기 위한 리스트 초기화
public static ArrayList<ArrayList<Integer>> graph = new ArrayList<>();
// 위상 정렬
public static void topologySort() {
Queue<Integer> q = new LinkedList<>(); // 큐 라이브러리 사용
// 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
for (int i = 1; i <= v; i++) {
if (indegree[i] == 0) {
q.offer(i);
}
}
// 큐가 빌 때까지 반복
while (!q.isEmpty()) {
// 큐에서 원소 꺼내기
int now = q.poll();
// 순서를 출력하려면, now를 출력
System.out.println(now);
// 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
for (int next : graph.get(now)) {
inDegree[next]--;
// 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
if (inDegree[next] == 0) {
q.offer(next);
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
v = sc.nextInt();
indegree = new int[v+1];
// 그래프 초기화
for (int i = 0; i <= v; i++) {
graph.add(new ArrayList<>());
}
// 방향 그래프의 모든 간선 정보를 입력받기 (a -> b)
for (int i = 0; i < e; i++) {
a = sc.nextInt(); // 선행
b = sc.nextInt(); // 후행
graph.get(a).add(b);
indegree[b]++ // 후행 노드의 진입 차수 + 1
}
topologySort();
}
}
코드 설명 (Step)
- 진입 차수가 0인 정점을 큐에 추가한다. (선행 조건이 없는 정점부터)
- 큐에 저장된 정점을 하나 꺼낸다.
- 꺼낸 정점과 연결된 정점을 찾고, 선행 조건인 정점이 처리 되었으므로 연결된 정점의 진입 차수를 하나 빼준다.
- 연결된 정점의 진입 차수가 0이라면(선행 조건 없음) 해당 정점을 큐에 추가한다.
- 큐가 빌 때 까지 2 ~ 4 번의 과정을 반복한다.
문제
'알고리즘' 카테고리의 다른 글
[알고리즘] 백준 2003번: 수들의 합 2 (자바/Java) - 슬라이딩 윈도우, 구간합 (2) | 2020.10.29 |
---|---|
[알고리즘] 백준 2839번: 설탕 배달 풀이 (자바/Java) DP,동적계획법, Dynamic Programming 기본 (0) | 2020.09.26 |
[알고리즘] 프로그래머스 무지의 먹방 라이브(Level 4/2019 카카오 블라인드 채용 문제) [자바/JAVA] 풀이- 개발하는 지토 (2) | 2020.09.07 |
[알고리즘] 프로그래머스 모의고사(Level 1) [자바/JAVA] 풀이- 개발하는 지토 (1) | 2020.09.03 |
[알고리즘] 프로그래머스 큰 수 만들기(Level 2) [자바/JAVA] 풀이- 개발하는 지토 (0) | 2020.09.02 |
댓글