๊นจ์•Œ ๊ฐœ๋… ๐Ÿ“‘/์•Œ๊ณ ๋ฆฌ์ฆ˜

๊ทธ๋ž˜ํ”„ - ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰ (DFS, Depth-First Search)

interfacer_han 2024. 9. 23. 20:27

#1 ๊ทธ๋ž˜ํ”„์˜ ํƒ์ƒ‰

 

๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰ - ์œ„ํ‚ค๋ฐฑ๊ณผ, ์šฐ๋ฆฌ ๋ชจ๋‘์˜ ๋ฐฑ๊ณผ์‚ฌ์ „

์œ„ํ‚ค๋ฐฑ๊ณผ, ์šฐ๋ฆฌ ๋ชจ๋‘์˜ ๋ฐฑ๊ณผ์‚ฌ์ „. ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰ ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์˜ˆ์‹œ ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰( - ๅ„ชๅ…ˆๆŽข็ดข, ์˜์–ด: depth-first search, DFS)์€ ๋งน๋ชฉ์  ํƒ์ƒ‰๋ฐฉ๋ฒ•์˜ ํ•˜๋‚˜๋กœ ํƒ์ƒ‰ํŠธ๋ฆฌ์˜ ์ตœ๊ทผ์— ์ฒจ๊ฐ€

ko.wikipedia.org

๊ทธ๋ž˜ํ”„์˜ ๊ฐ ์ •์ ์„ ํ•œ๋ฒˆ์”ฉ ๋ฐฉ๋ฌธํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•ด๋ณด์ž. ๊ทธ ๋ฐฉ๋ฌธ์˜ ๋ฐฉ๋ฒ•์—๋Š” ํฌ๊ฒŒ 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ํ•˜๋‚˜๋Š” ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์ด๋‹ค. ๋˜ ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰์ด๋‹ค. ๋ณธ ๊ฒŒ์‹œ๊ธ€์—์„œ๋Š” ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰๋ฒ•์„ ๋‹ค๋ฃฌ๋‹ค. (๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰์— ๋Œ€ํ•ด์„œ๋Š” ์ด ๊ฒŒ์‹œ๊ธ€์—์„œ ๋‹ค๋ฃฌ๋‹ค)
 

#2 ์•Œ๊ณ ๋ฆฌ์ฆ˜

https://commons.wikimedia.org/wiki/File:Depth-first-tree.svg

์›๋ž˜๋ผ๋ฉด ์ˆœ์„œ๋„๋ฅผ ํ†ตํ•ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์†Œ๊ฐœํ•˜๊ณ  ์ฝ”๋“œ๋กœ ๋„˜์–ด๊ฐ€๋Š” ํŽธ์ด ์ดํ•ดํ•˜๊ธฐ ์ข‹์ง€๋งŒ, ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ทธ๋ƒฅ ์ฝ”๋“œ๋ถ€ํ„ฐ ๋ณด๋Š” ๊ฒŒ ์˜คํžˆ๋ ค ์ดํ•ด๊ฐ€ ๋” ๋น ๋ฅด๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ๋‹ค๋งŒ, ์ธ์ ‘ ๋ฐฐ์—ด (Adjacency Array)์˜ ์ง€์‹์— ๋Œ€ํ•ด์„œ๋Š” ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ „์ œ ํ•˜๋‹ค. ์—ฌ๊ธฐ์„œ ์‚ฌ์šฉํ•  ์ธ์ ‘ ๋ฐฐ์—ด์€ ์ด ๊ฒŒ์‹œ๊ธ€์— ์žˆ๋‹ค (๊ฐ€์ค‘์น˜๊ฐ€ ์—†๋Š” ๋ฌดํ–ฅ ๊ทธ๋ž˜ํ”„).

๋Œ€์‹  ์™œ '๊นŠ์ด ์šฐ์„ ' ํƒ์ƒ‰์ด๋ผ๋Š” ์ด๋ฆ„์ด ๋ถ™์—ˆ๋Š”์ง€๋Š” ์„ค๋ช…ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค. ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์€ ๋‹ค๋ฅธ ๋ง๋กœ '์ฒซ๋ฒˆ์งธ ์ž์‹ ์šฐ์„ ' ํƒ์ƒ‰์ด๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๊ทธ๋ž˜ํ”„๋Š” ๊นŠ์ด์˜ ๋†’๋‚ฎ์ด๊ฐ€ ์œ„ ๊ทธ๋ž˜ํ”„์ฒ˜๋Ÿผ y์ถ•๊ณผ ํ‰ํ–‰ํ•˜๊ฒŒ ๊ทธ๋ ค์ง„๋‹ค. ๋”ฐ๋ผ์„œ '์ฒซ๋ฒˆ์งธ ์ž์‹ ์šฐ์„ '์œผ๋กœ ํƒ์ƒ‰ํ•œ๋‹ค๋Š” ๋ง์€, 2 → 3 → 4 → 5 → 6 → 7 → 8์™€ ๊ฐ™์€ ์‹์œผ๋กœ ํƒ์ƒ‰ํ•œ๋‹ค๋Š” ๋ง์ด ๋œ๋‹ค. ์ด ํƒ์ƒ‰์€ y์ถ•(๋†’์ด)๋ฅผ ์šฐ์„ ํ•ด ์ด๋™ํ•˜๋Š” ๋ชจ์–‘์ด ๋œ๋‹ค (x์ถ• ์ด๋™์€ y์ถ• ํƒ์ƒ‰์ด ์ข…๋ฃŒ๋œ ํ›„์— ์‹œํ–‰๋œ๋‹ค. ์šฐ์„ ์ˆœ์œ„๊ฐ€ ์•„๋‹Œ ๊ฒƒ์ด๋‹ค). ๊ทธ๋ž˜์„œ ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์ด๋ผ ๋ถ€๋ฅธ๋‹ค.
 

#3 ์ฝ”๋“œ - ์ฝ”ํ‹€๋ฆฐ

#3-1 ๊ธฐ๋ณธ ์ฝ”๋“œ

fun main() {
    // (1) listOfAdjacencyArray[n]์ด ๊ฐ€์ง€๋Š” ์˜๋ฏธ๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค (์„ค๋ช… ์ฐธ์กฐ)
    val listOfAdjacencyArray = listOf(
        arrayOf(1, 2),
        arrayOf(0, 3, 4),
        arrayOf(0, 4),
        arrayOf(1),
        arrayOf(1, 2)
    )

    // (2) visited๋Š” ๋ฐฉ๋ฌธ์ด ์™„๋ฃŒ๋œ ์ •์ ๋“ค์„ ๊ธฐ๋กํ•˜๋Š” Set(์ง‘ํ•ฉ)์ด๋‹ค
    val visited = mutableSetOf<Int>()
    dfs(listOfAdjacencyArray, 0, visited)  // 0๋ฒˆ ์ •์ (vertex)์—์„œ ํƒ์ƒ‰ ์‹œ์ž‘
}

fun dfs(listOfAdjacencyArray: List<Array<Int>>, vertex: Int, visited: MutableSet<Int>) {
    // (3) ๋งค๊ฐœ๋ณ€์ˆ˜ ์ •์ ์„ visited์— ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฐฉ๋ฌธํ•ด์„œ ์ง„ํ–‰ํ•  ์ผ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์—ฌ๊ธฐ์„  doSomethingFunction()์œผ๋กœ ํ‘œํ˜„ํ–ˆ๋‹ค
    visited.add(vertex)
//  doSomethingFunction(vertex)
    println("Visit complete: $vertex")

    // (4) ์ •์ ์˜ ์ด์›ƒ ์ •์ ๋งˆ๋‹ค (5)์„ ์ˆ˜ํ–‰
    for (neighborVertex in listOfAdjacencyArray[vertex]) {
        // (5) visited ๋ชฉ๋ก์— ์—†๋‹ค๋ฉด, ์ด์›ƒ ์ •์ ์„ ์žฌ๊ท€ ํ˜ธ์ถœํ•œ๋‹ค
        if (neighborVertex !in visited) {
            dfs(listOfAdjacencyArray, neighborVertex, visited)
        }
    }
}

(1) listOfAdjacencyArray[n]์ด ๊ฐ€์ง€๋Š” ์˜๋ฏธ๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค
์ •์ ์— ๋ถ€์—ฌ๋œ ๋ฒˆํ˜ธ๊ฐ€ 0 ~ N์ผ ๋•Œ, listOfAdjacencyArray[n]์€ n๋ฒˆ ์ •์ ์— ์—ฐ๊ฒฐ๋œ ์ด์›ƒ(neighbor) ์ •์ ๋“ค์˜ ๋ฐฐ์—ด์„ ์˜๋ฏธํ•œ๋‹ค.

(2) visited๋Š” ๋ฐฉ๋ฌธ์ด ์™„๋ฃŒ๋œ ์ •์ ๋“ค์„ ๊ธฐ๋กํ•˜๋Š” Set(์ง‘ํ•ฉ)์ด๋‹ค
bfs์™€ ๋‹ฌ๋ฆฌ visited๊ฐ€ ๋ฐ–์— ๋‚˜์™€ ์žˆ๋‹ค. dfs์˜ ๊ตฌ์กฐ(์žฌ๊ท€ ํ˜ธ์ถœ) ๋•Œ๋ฌธ์— ๊ทธ๋ ‡๋‹ค

(3) ๋งค๊ฐœ๋ณ€์ˆ˜ ์ •์ ์„ visited์— ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฐฉ๋ฌธ...
bfs์— ๋Œ€ํ•ด ๋‹ค๋ฃฌ ์ด ๊ฒŒ์‹œ๊ธ€๊ณผ ๋‹ฌ๋ฆฌ, Setํ˜• ๋ณ€์ˆ˜ ์ด๋ฆ„์„ visited๋ผ๊ณ  ๋‘์—ˆ๋‹ค. bfs์—์„œ์™€ ๋‹ฌ๋ฆฌ ๋ณธ ๊ฒŒ์‹œ๊ธ€(dfs)์—์„œ๋Š”, ์–ด๋–ค ์ •์ ์„ Set์— ๋„ฃ์Œ(add())๊ณผ ๋™์‹œ์— ํ•ด๋‹น ์ •์ ์— '๋ฐฉ๋ฌธ'ํ•œ ๊ฒƒ์œผ๋กœ ์ทจ๊ธ‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

(4) ์ •์ ์˜ ์ด์›ƒ ์ •์ ๋งˆ๋‹ค (5)์„ ์ˆ˜ํ–‰
listOfAdjacencyArray[n]์€ ๋ฐฉ๊ธˆ ๋ฐฉ๋ฌธ ์™„๋ฃŒํ•œ ์ •์  n์— ์—ฐ๊ฒฐ๋œ ์ด์›ƒ ์ •์ ๋“ค์˜ ๋ฐฐ์—ด์ด๋‹ค. ์ด ๋ฐฐ์—ด์˜ ์š”์†Œ๋งˆ๋‹ค (5)์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

(5) visited ๋ชฉ๋ก์— ์—†๋‹ค๋ฉด, ์ด์›ƒ ์ •์ ์„ ์žฌ๊ท€ ํ˜ธ์ถœํ•œ๋‹ค
์žฌ๊ท€ ํ˜ธ์ถœ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์žฌ๊ท€ ํ˜ธ์ถœ์€ ์Šคํƒ ๊ตฌ์กฐ๋ฅผ ์ด๋ฃฌ๋‹ค. ์ฆ‰, ๊ฐ€์žฅ ๋Šฆ๊ฒŒ(์ตœ๊ทผ์—) ์žฌ๊ท€ ํ˜ธ์ถœ๋œ dfs()๊ฐ€ ๋จผ์ € ์ฒ˜๋ฆฌ๋œ๋‹ค (ํ›„์ž… ์„ ์ถœ). #2์—์„œ ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์„ '์ฒซ๋ฒˆ์งธ ์ž์‹ ์šฐ์„ ' ํƒ์ƒ‰์ด๋ผ๊ณ  ๋งํ•œ ์ด์œ ๋‹ค. ๊ฐ ์žฌ๊ท€ ํ˜ธ์ถœ์€ listOfAdjacencyArray[vertex]์˜ ์ฒซ๋ฒˆ์งธ ์›์†Œ ์ฆ‰ listOfAdjacencyArray[vertex][0]๋ถ€ํ„ฐ ์ˆ˜ํ–‰๋œ๋‹ค. ๋˜, ํ•ด๋‹น ์žฌ๊ท€ ํ˜ธ์ถœ์—์„œ ์—ฐ์‡„์ ์œผ๋กœ ๋ฐœ์ƒํ•  ์žฌ๊ท€ ํ˜ธ์ถœ ๋˜ํ•œ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ธ์ ‘ ๋ฐฐ์—ด์— ์ ํžŒ ์ฒซ๋ฒˆ์งธ ์›์†Œ๋ถ€ํ„ฐ ์ˆ˜ํ–‰๋  ๊ฒƒ์ด๋‹ค.

#3-2 ์ œ๋„ค๋ฆญ์„ ์ด์šฉํ•œ ์ฝ”๋“œ

import kotlin.collections.HashMap

fun main() {
    // (1) mapOfAdjacencyArray[n]์ด ๊ฐ€์ง€๋Š” ์˜๋ฏธ๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค (์„ค๋ช… ์ฐธ์กฐ)
    val mapOfAdjacencyArray = HashMap<String, Array<String>>()
    mapOfAdjacencyArray["๊ฐ•์•„์ง€"] = arrayOf("๊ณ ์–‘์ด", "์‚ฌ์Šด")
    mapOfAdjacencyArray["๊ณ ์–‘์ด"] = arrayOf("๊ฐ•์•„์ง€", "์ฝ”๋ฟ”์†Œ", "ํฐ๋จธ๋ฆฌ์˜ค๋ชฉ๋ˆˆ์ด")
    mapOfAdjacencyArray["์‚ฌ์Šด"] = arrayOf("๊ฐ•์•„์ง€", "ํฐ๋จธ๋ฆฌ์˜ค๋ชฉ๋ˆˆ์ด")
    mapOfAdjacencyArray["์ฝ”๋ฟ”์†Œ"] = arrayOf("๊ณ ์–‘์ด")
    mapOfAdjacencyArray["ํฐ๋จธ๋ฆฌ์˜ค๋ชฉ๋ˆˆ์ด"] = arrayOf("๊ณ ์–‘์ด", "์‚ฌ์Šด")

    // (2) visited๋Š” ๋ฐฉ๋ฌธ์ด ์™„๋ฃŒ๋œ ์ •์ ๋“ค์„ ๊ธฐ๋กํ•˜๋Š” Set(์ง‘ํ•ฉ)์ด๋‹ค
    val visited = mutableSetOf<String>()
    dfs(mapOfAdjacencyArray, "๊ฐ•์•„์ง€", visited)  // "๊ฐ•์•„์ง€" ์ •์ (vertex)์—์„œ ํƒ์ƒ‰ ์‹œ์ž‘
}

fun <T> dfs(mapOfAdjacencyArray: Map<T, Array<T>>, vertex: T, visited: MutableSet<T>) {
    // (3) ๋งค๊ฐœ๋ณ€์ˆ˜ ์ •์ ์„ visited์— ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฐฉ๋ฌธํ•ด์„œ ์ง„ํ–‰ํ•  ์ผ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์—ฌ๊ธฐ์„  doSomethingFunction()์œผ๋กœ ํ‘œํ˜„ํ–ˆ๋‹ค
    visited.add(vertex)
//  doSomethingFunction(vertex)
    println("Visit complete: $vertex")

    // (4) ์ •์ ์˜ ์ด์›ƒ ์ •์ ๋งˆ๋‹ค (5)์„ ์ˆ˜ํ–‰
    for (neighborVertex in mapOfAdjacencyArray[vertex]!!) {
        // (5) visited ๋ชฉ๋ก์— ์—†๋‹ค๋ฉด, ์ด์›ƒ ์ •์ ์„ ์žฌ๊ท€ ํ˜ธ์ถœํ•œ๋‹ค
        if (neighborVertex !in visited) {
            dfs(mapOfAdjacencyArray, neighborVertex, visited)
        }
    }
}

์ง€๊ธˆ๊นŒ์ง€ ์ •์ ์„ ํŽธ์˜์ƒ Intํ˜•์ด๋ผ๊ณ ๋งŒ ๋‹ค๋ค˜์ง€๋งŒ, ์ •์ ์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ธฐ์ค€์ด ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐํ˜•์ผ ์ˆ˜๋„ ์žˆ๋‹ค. ๊ทธ ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๋„ค๋ฆญ์„ ์ด์šฉํ•ด ๋ฆฌํŒฉํ† ๋งํ•œ ์ฝ”๋“œ๋‹ค. listOfAdjacencyArray๊ฐ€ mapOfAdjacencyArray๋กœ ๋ฐ”๋€ ๊ฒƒ์—๋„ ์ฃผ๋ชฉํ•˜์ž. listOfAdjacencyArray์˜ index๋Š” ๋ฐ˜๋“œ์‹œ Int์—ฌ์•ผ ํ•œ๋‹ค๋Š” ์ œ์•ฝ ์กฐ๊ฑด์ด ์žˆ๊ธฐ์— ์ด index์˜ ์—ญํ• ์„, mapOfAdjacencyArray์˜ key๊ฐ€ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค.

 

#4 ์š”์•ฝ

๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์€ ์ธ์ ‘ ๋ฐฐ์—ด์˜ ์›์†Œ๋“ค์„ (์žฌ๊ท€ ํ˜ธ์ถœ ๊ตฌ์กฐ๋ผ๋Š”) Stack์— ๋„ฃ๋Š”๋‹ค.