- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- Java
- 연결리스트
- 프로그래밍 입문
- firebase google
- 프로그래머스
- sql
- 코딩테스트
- 자바
- 비주얼 베이직
- C++
- android studio
- python
- 알고리즘
- 백준
- 구글 로그인
- 안드로이드 스튜디오
- 자료구조
- til
- Firebase
- 컴퓨터공학과
- 배열
- 파이썬
- C언어
- 공유대학
- 안드로이드
- oauth
- 로그인
- 동적할당
- 정렬
Archives
코딩하는 해달이
[알고리즘] 위상 정렬 본문
위상 정렬
위상 정렬은 주로 작업 순서를 정하거나 의존성 관계를 해결할 때 사용하는 알고리즘으로 정점들의 선행 순서를 위배하지 않으면서 모든 정점을 나열하는 알고리즘이다.
특징
- 비순환 방향 그래프에서만 적용이 가능하다.
- 정렬 결과가 여러가지 일 수 있다.
- 사이클이 있는 그래프에서는 위상 정렬이 불가능하다.
- 사이클 : 한 정점에서 출발하여 간선과 정점을 지나 다시 출발했던 정점으로 돌아오는 것
알고리즘 구현 방법
- DFS(깊이 우선 탐색) 기반 방법 : 그래프를 DFS로 탐색하며 탐색이 끝나느 정점부터 스택에 삽입, 스택에서 꺼내는 순서가 정렬의 결과
- 진입차수 기반 방법 : 진입차수가 0인 정점을 큐에 넣고 하나씩 꺼내면서 간선을 제거, 큐에서 꺼내는 순서가 정렬의 결과
시간 복잡도
O(V + E) (V : 정점의 수, E : 간선의 수)
예제(진입차수 기반 방법)
위의 그래프를 이용해 위상정렬을 순서대로 진행해보자
1. 진입차수를 확인한다(진입 차수 : 해당 정점을 향하는 간선의 수)
2. 큐에 진입차수가 0인 정점을 넣는다.
3. 큐에서 순서대로 정점을 꺼내고 해당 정점의 간선을 제거한다.
4. 다시 처음으로 돌아가서 반복한다.
import java.util.*;
public class TopologicalSort {
private int V; // 정점의 수
private ArrayList<ArrayList<Integer>> adj; // 인접 리스트
public TopologicalSort(int v) {
V = v;
adj = new ArrayList<>(V);
for (int i = 0; i < V; i++) {
adj.add(new ArrayList<>());
}
}
// 간선 추가 (v -> w)
public void addEdge(int v, int w) {
adj.get(v).add(w);
}
// 위상 정렬 수행
public ArrayList<Integer> topologicalSort() {
int[] inDegree = new int[V]; // 각 정점의 진입차수
ArrayList<Integer> result = new ArrayList<>(); // 정렬 결과
// 모든 정점의 진입차수 계산
for (int i = 0; i < V; i++) {
for (int node : adj.get(i)) {
inDegree[node]++;
}
}
// 진입차수가 0인 정점을 큐에 삽입
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < V; i++) {
if (inDegree[i] == 0) {
queue.offer(i);
}
}
// 위상 정렬 알고리즘 수행
while (!queue.isEmpty()) {
int v = queue.poll();
result.add(v);
// 해당 정점과 연결된 모든 정점들의 진입차수를 1 감소
for (int adj : adj.get(v)) {
if (--inDegree[adj] == 0) {
queue.offer(adj);
}
}
}
// 모든 정점을 방문하지 못했다면 사이클이 존재한다는 의미
if (result.size() != V) {
System.out.println("그래프에 사이클이 존재합니다.");
return new ArrayList<>();
}
return result;
}
public static void main(String[] args) {
TopologicalSort g = new TopologicalSort(8);
g.addEdge(1, 2);
g.addEdge(1, 5);
g.addEdge(2, 3);
g.addEdge(3, 4);
g.addEdge(4, 6);
g.addEdge(5, 3);
g.addEdge(5, 6);
g.addEdge(6, 7);
ArrayList<Integer> sortedOrder = g.topologicalSort();
System.out.println("위상 정렬 결과: " + sortedOrder);
}
}
반응형
'개인 공부 > 알고리즘&자료구조' 카테고리의 다른 글
[정렬] 선택 정렬 (0) | 2024.10.30 |
---|---|
[정렬] 버블 정렬 (0) | 2024.10.28 |
[알고리즘] 임의의 좌표가 원을 기준으로 어디에 위치하고 있는지 확인 (0) | 2023.02.24 |
[자료구조] 자료구조 수업 과제 2 (0) | 2022.11.19 |
[자료구조] 자료구조 수업 과제 1 (0) | 2022.11.19 |
Comments