위상 정렬에 대해 알아보자.
여러 방법이 있지만,
여기서는 DFS와 Stack를 이용해서 구현해보겠다.
선행 조건들을 만족하는 일의 수행 순서.
특정 노드를 방문하려면, 조건으로 갖는 다른 노드들이 방문된 상태여야 함.
조건을 지키면서 노드 방문 순서를 짜는 것을 위상 정렬이라고 한다.
선수 과목
(1) 과목 2의 선수 과목은 과목 1이다.
(2) 과목 4의 선수 과목은 과목 1, 2, 3이다.
(3) 과목 5의 선수 과목은 과목 3이다.
(4) 과목 6의 선수 과목은 과목 2, 4, 5이다.
(5) 과목 7의 선수 과목은 과목 5, 6이다.
그림으로 그려보자.
위와 같은 그림을 얻게 된다.
import java.util.*;
class Main {
public static void main(String[] args) {
Node[] node = new Node[8];
for(int i=0; i<node.length; i++)
node[i] = new Node(i);
node[0].addNeighbours(node[1]);
node[0].addNeighbours(node[3]);
node[1].addNeighbours(node[2]);
node[1].addNeighbours(node[4]);
node[2].addNeighbours(node[4]);
node[2].addNeighbours(node[6]);
node[3].addNeighbours(node[4]);
node[3].addNeighbours(node[5]);
node[4].addNeighbours(node[6]);
node[5].addNeighbours(node[6]);
node[5].addNeighbours(node[7]);
node[6].addNeighbours(node[7]);
System.out.println("위상 정렬 순서");
node[0].visited = true;
topoSort(node[0]);
while(!stack.empty())
System.out.println(stack.pop()+" ");
}
static Stack<Node> stack = new Stack<>();
static void topoSort(Node v) {
List<Node> neighbours = v.getNeighbours();
for(Node w : neighbours){
if(!w.visited){
w.visited=true;
topoSort(w);
}
}
stack.push(v);
}
}
class Node {
int info;
boolean visited;
List<Node> neighbours; //인접 목록
Node(int info){ //생성자
this.info = info;
this.visited = false;
this.neighbours = new ArrayList<>();
}
public void addNeighbours(Node neighbourNode) { //인접 목록 채우기
this.neighbours.add(neighbourNode);
}
public List<Node> getNeighbours(){ //인접 목록 반환
return neighbours;
}
public void setNeighbours(List<Node> neighbours) { // 인접 목록 세팅
this.neighbours = neighbours;
}
@Override
public String toString() { //출력 오버라이딩
return "" + info;
}
}
DFS와 Stack으로 구현되는게 좀 이해가 안됐는데,
진출 간선이 없는 노드부터 하나씩 빼서 stack에 저장한다고 생각하면 된다.
이렇게 생각하면 Queue로 구현하는 것의 역순으로 알고리즘이 진행된다는 것을 알 수 있다.
이해가 안됬는데(×)
이해가 안됐는데(○)