Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 |
Tags
- 디자인패턴 #
- El
- 팩토리 메소드
- 옵저버 패턴
- PrototypePattern
- 프로토타입 패턴
- F
- 빌터패턴
- ㅋㅁ
- 싱글톤
- r
- 함수형프로그래밍
- designPattern
- ㅓ
- 추상 팩토리
- 디자인패턴
- Design Pattern
- Functional Programming
- Observer Pattern
- Kotlin
- factory method
- Abstract Factory
- builderPattern
- 추상팩토리패턴
- Singleton
- a
- 코틀린
Archives
- Today
- Total
오늘도 더 나은 코드를 작성하였습니까?
그래프 탐색 - 깊이우선 탐색 (DFS Depth-First Search) feat.kotlin 본문
정의
그래프를 탐색 하는 방법중 하나이다.
그래프에서는 탐색을 시작하는 노드를 시작으로 인접한 노드로 지속적으로 이동한다.
더 이상 탐색을 하지 않은 인접한 노드가 없을 때 까지 탐색을 진행후, 부모노드로 돌아와서 탐색하지 않은 인접한 노드를 탐색한다.
인접한 모든 노드가 탐색이 완료되면 종료한다.
* 탐색은 한번 방문한 노드는 다시 방문하지 않습니다. (부모노드로 돌아오는것 이외에)
* 현재 노드에서 다음 노드로 이동시 인접한 노드중에 선택하는 기준은 위 그림에선 왼쪽 --> 오른쪽이다.
V - 정점(노드)의 개수
E - 간선의 개수
인접리스트로 표현된 자료구조로 탐색 했다면
시간복잡도 - O(V + E)
인접행렬로 표현된 자료구조로 탐색 했다면 (시간 복잡도가 크기 때문에 인접리스트로 바꾸어 탐색)
시간복잡도 O(V^2)
완전탐색 및 백트레킹에 많이 쓰임.
깊이 탐색할때, 인접한 노드중에 탐색 순서의 기준도 중요함.
특정 조건의 여부에 따라 탐색을 중단하는것에 유용함.
재귀함수를 이용한 구현
// 그래프 탐색 DFS
private val vNum = 6
val adj = Array(vNum) { mutableListOf<Int>() }
val visited = Array(vNum) { 0 }
fun dfs(g: Array<MutableList<Int>>, v: Int) {
println("v: $v")
visited[v] = 1
for (nv in adj[v]) {
if (visited[nv] == 1) continue
dfs(g, nv)
}
}
fun draw(){
adj[1].add(2)
adj[1].add(4)
adj[2].add(1)
adj[2].add(3)
adj[3].add(2)
adj[3].add(5)
adj[4].add(1)
adj[5].add(3)
}
fun main() {
draw()
dfs(adj, 1)
println(visited.joinToString())
}
/*
맵(2차원 배열) 탐색 DFS
맵의 특정 위치는 y(row) x(col)로 좌표로 나타낸다.
Pair<Int, Int> 또는 2개의 Int Type 파라미터를 필요로 한다.
아래 코드는 맵을 탐색하면서 연결된 덩어리 지역을 방문을 표기한다.
nxn 의 정사각의 맵이 주어졌다면,
V = n*n개
E = (n-1)(2n)개
시간 복잡도는
O(n^2 + 2n^2 - 2n)
--> O(n^2)
*/
val map = arrayOf(
intArrayOf(1, 0, 1, 0, 1),
intArrayOf(1, 1, 0, 0, 1),
intArrayOf(0, 0, 0, 1, 1),
intArrayOf(0, 0, 0, 1, 1),
intArrayOf(0, 1, 0, 0, 0),
)
val dy = arrayOf(-1, 0, 1, 0)
val dx = arrayOf(0, 1, 0, -1)
val rows = 5
val cols = 5
val visited = Array(rows) { IntArray(cols) { 0 } }
fun mDfs(map: Array<IntArray>, p: Pair<Int, Int>) {
visited[p.first][p.second] = 1
for (i in 0 until 4) {
val ny = p.first + dy[i]
val nx = p.second + dx[i]
if (ny !in 0 until map.size || nx !in 0 until map.first().size) continue
if (map[ny][nx] == 1 && visited[ny][nx] != 1) {
mDfs(map, ny to nx)
}
}
}
fun main() {
var connectedComponentCnt = 0
for (i in 0 until rows) {
for (j in 0 until cols) {
if (map[i][j] == 1 && visited[i][j] != 1) {
connectedComponentCnt += 1
mDfs(map, i to j)
}
}
}
visited.forEach { println(it.joinToString()) }
println(connectedComponentCnt)
}
'Algorithm > 개념' 카테고리의 다른 글
이진법과 비트 연산 feat.kotlin (1) | 2023.10.21 |
---|---|
그래프 탐색 - 너비우선 탐색 (BFS Breadth-First Search) feat.kotlin (0) | 2023.10.13 |
그래프(graph)의 기본 개념(feat.kotlin) (2) | 2023.10.12 |
모듈러 연산. (0) | 2023.08.26 |
Algorithm(알고리즘) 병합 정렬(merge sort) 정리 feat. kotlin (0) | 2023.08.17 |