안녕하세요. CalKim 입니다.
어제 카카오 공채 공고가 떴더라구요.
https://careers.kakao.com/2022-developer
2022 카카오 신입개발자 블라인드 채용
카카오에서 더나은 세상을 함께 만들어 봐요
careers.kakao.com
저는 코딩테스트 볼 때 DFS, BFS만 나오면 겁을 먹곤해서
언젠가 한 번 제대로 공부해야겠단 생각이 들었습니다.
그 언젠가가 바로 오늘인 것 같습니다. 캬컄캬캬컄
그런 의미에서 오늘은 스위프트를 이용하여 DFS 알고리즘을 구현해보도록 하겠습니다.
DFS 알고리즘이란
우선 간단히 DFS가 무엇인지 살펴보겠습니다.
DFS 는 Depth-First Search, 깊이 우선 탐색이라고 합니다.
이 방법은
그래프를 탐색할 때,
선택된 탐색방향으로 최대한 깊이 탐색을 하고
더 이상 깊어질 수 없을 때,
옆을 탐색합니다.
위와 같은 그래프가 있다고 하겠습니다.
이 그래프에서 깊이우선탐색을 적용하면,
위와 같이 한 방향으로 최대한 깊이 내려가고
3번에서 더 이상 갈 곳이 없으므로
옆을 탐색하게 됩니다.
또, 4번에서 더 이상 깊이 들어갈 수 없으므로,
하나씩 거슬러 올라가서 옆으로 빠질 길이 없나 살펴봅니다.
4번은 형제 노드가 더 이상 없으므로
2번의 형제 노드를 살피게 되고
마찬가지로 깊이 우선으로 탐색하게 됩니다.
따라서 이와 같은 순서로 탐색을 하게 됩니다.
DFS 구현하기 - 그래프 만들기
이번에는 위에서 만든 그래프를 구현하고 깊이우선탐색을 적용시켜보도록 하겠습니다.
우선 노드를 구성해주도록 하겠습니다.
각각의 노드는
부모노드와 자식 노드에 대한 정보를 가지고 있고,
탐색되었는지에 대한 프로퍼티가 있으면 될 것 같습니다.
class Node {
var parent: Node?
var child: [Node] = []
var visited: Bool = false
}
따라서 노드는 위의 클래스와 같이 정의하였습니다.
이번에는 아래의 그래프 구성과 같이 노드를 만들겠습니다.
let a = Node()
let b = Node()
let c = Node()
let d = Node()
let e = Node()
let f = Node()
let g = Node()
a.child = [b,c]
b.child = [d,e]
c.child = [f,g]
음.... 왜 c 노드만 색깔이 다르게 나오는지는 모르겠지만....
시작 노드가 a라는 점만 알고 시작하도록 하겠습니다.
우선 DFS 함수의 틀을 잡아주었습니다.
func dfsSearch(_ startNode: Node) {
//
}
startNode 를 받고나면 해당 노드의 visited 값을 true 로 바꿔줍니다.
그리고 함수 실행시 어떤 노드가 어떻게 바뀌는지 확인하기 위한 명령어를 넣도록 하겠습니다.
func dfsSearch(_ startNode: Node) {
startNode.visited = true
print("a: \(a.visited) b: \(b.visited) c: \(c.visited) d: \(d.visited) e: \(e.visited) f: \(f.visited) g: \(g.visited)")
}
이제부터 자식노드들을 살펴보기 시작합니다.
func dfsSearch(_ startNode: Node) {
startNode.visited = true
print("a: \(a.visited) b: \(b.visited) c: \(c.visited) d: \(d.visited) e: \(e.visited) f: \(f.visited) g: \(g.visited)")
startNode.child.forEach({
//
})
}
자식노드마다 dfsSearch를 재귀적으로 호출해줍니다.
그렇게되면 자식은 자식의 자식을, 그 자식은 또 자신의 자식을 살펴보며,
깊이우선 탐색이 적용됩니다.
func dfsSearch(_ startNode: Node) {
startNode.visited = true
print("a: \(a.visited) b: \(b.visited) c: \(c.visited) d: \(d.visited) e: \(e.visited) f: \(f.visited) g: \(g.visited)")
startNode.child.forEach({
dfsSearch($0)
})
}
이것으로 깊이 우선 탐색 코드 작성이 끝났습니다.
실행시켜보도록 하겠습니다.
dfsSearch(a)
우리가 기대했던대로,
a, b, d, e, c, f, g 순서대로 탐색된 것을 확인할 수 있습니다.
이것으로 DFS를 재귀를 이용하여 구현해보았습니다.
막상 해보니까 크게 어렵지는 않은데,
재귀함수에 대한 부담감 때문에 그동안 부담스러워했던 것 같네요.
그럼 오늘 짠 DFS 코드 전문을 올리며 마치도록 하겠습니다.
읽어주셔서 감사합니다.
import Foundation
class Node {
var parent: Node?
var child: [Node] = []
var visited: Bool = false
}
let a = Node()
let b = Node()
let c = Node()
let d = Node()
let e = Node()
let f = Node()
let g = Node()
a.child = [b,c]
b.child = [d,e]
c.child = [f,g]
func dfsSearch(_ startNode: Node) {
startNode.visited = true
print("a: \(a.visited) b: \(b.visited) c: \(c.visited) d: \(d.visited) e: \(e.visited) f: \(f.visited) g: \(g.visited)")
startNode.child.forEach({
dfsSearch($0)
})
}
dfsSearch(a)
* 이 게시글에서 내용 상의 틀린 점 혹은 더 알아야 할 점 등이 있다면 알려주시면 감사히 배우겠습니다
'알고리즘' 카테고리의 다른 글
코테 준비하다 정리하는 정렬 알고리즘 with python(선택) (1) | 2021.02.05 |
---|