스택 오버플로우(stack overflow)
스택 오버 플로우는 지정한 스택 메모리 사이즈보다 더 많은 스택 메모리를 사용하게 되어 에러가 발생하는 상황을 일컫는다.
시간복잡도(노드 수: N, 에지 수 E)
- O(N+E)
- 모든 노드를 한번씩 방문하고, 모든 에지를 한번씩 검사하기 때문에 V+E라고 할수 있다.
이 글에선 인접리스트로 표현하는 경우만 다뤘지만, 인접 행렬로 표현하는 방법도 있다.
인접 행렬로 표현하면 시간복잡도는 O(N^2)가 된다.
1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|
T | F | F | F | F | F |
boolean[] arr = new boolean[7];
으로 배열을 만들어 준다.
(편의를 위해 pop() 괄호 안에 값을 넣도록 하겠다.)
1. 위에서 1이 pop되고, 2,3이 스택에 들어있는 상황이다.
2. pop(3)
-> 3의 방문배열 True -> 3의 인접노드 push(4)
3. pop(4)
-> 4의 방문배열 True -> 4의 인접노드 push(6)
4. pop(6)
-> 6의 방문배열 True -> 6은 인접노드가 없기 때문에 push할 노드는 없다.
5. pop(2)
-> 2의 인접노드는 5,6이지만 6의 방문배열은 True 이므로 push(5)
만 할수 있다.
6. pop(5)
-> 5의 방문배열 True
7. stack.isEmpty() == true
- 마지막으로 pop(5)를 하고 나니, 스택이 비워졌다. -> 반복 종료
- 결과적으로 탐색 순서는 [ 1 - 3 - 4 - 6 - 2 - 5 ]이다.
실제로는 스택보다는 재귀함수를 이용해서 구현하는 경우가 많다.
재귀함수(Recursion)는 정의 단계에서 자신을 재참조하는 함수를 뜻한다. 어떤 사건이 자신을 포함하고 다시 자기 자신을 사용하여 정의될 때 재귀적(recursive)이라고 한다.
static boolean[] visited = new boolean[7]; //방문 배열
static ArrayList<Integer>[] A = new ArrayList[7];//ArrayList타입 배열
static ArrayList<Integer> procedure = new ArrayList<>(); //탐색 순서 list
public static void main(String[] args){
for(int i=1;i<=6;i++) {
A[i] = new ArrayList<>();//배열의 각 요소마다 ArrayList를 가진다.
}
//예제에서 노드1의 경우 3이 먼저,
//노드2의 경우 6이 먼저 실행하기 때문에 순서를 바꿔줌
A[1].add(3);
A[1].add(2);
A[2].add(6);
A[2].add(5);
A[3].add(4);
A[4].add(6);
//1번노드에서 DFS 실행
DFS(1);
System.out.println(procedure.toString()); // [1, 3, 4, 6, 2, 5]
}
static void DFS(int v){
//방문배열이 true면 return
if(visited[v]) return;
//v 노드에 방문했으므로, 해당 방문배열을 true로 바꿔주고, 탐색순서 리스트에 추가해줌
visited[v] = true;
procedure.add(v);
//해당노드의 ArrayList(인접노드)를 모두 돌며 방문배열이 false인 경우에
for(int i : A[v]){
if(!visited[i]){
DFS(i); //해당 노드에 대해서 DFS를 다시 실행한다.
}
}
}
(출처) Do it! 알고리즘 코딩 테스트 자바 편 e-book
http://www.yes24.com/Product/Goods/108571508