๐[Search] DFS์ ๋ํด์โฆ
๊ทธ๋ํ ํ์
๊ทธ๋ํ ํ์
์ด๋, ํ๋์ ์ ์ ์ผ๋ก๋ถํฐ ์์ํด์ ์ฐจ๋ก๋๋ก ๋ชจ๋ ์ ์ ๋ค์ ํ ๋ฒ์ฉ ๋ฐฉ๋ฌธํ๋ ๋์์ ๋งํ๋ค.
๊ทธ๋ํ ํ์์ ์ฐ์ด๋ ์๊ณ ๋ฆฌ์ฆ์ ๋ง์ง๋ง, ๊ทธ ์ค ๊ฐ์ฅ DFS
์ ๋ํด์ ์ ๋ฆฌํ๋ค.
DFS(Depth First Search) - ๊น์ด ์ฐ์ ํ์
DFS
๋, ๋ฃจํธ๋
ธ๋์์ ์์ํด, ๋ค์ ๋ถ๊ธฐ(branch)๋ก ๋์ด๊ฐ๊ธฐ ์ ์ ํด๋น ๋ถ๊ธฐ๋ฅผ ์๋ฒฝํ๊ฒ ํ์ํ๋ ๋ฐฉ๋ฒ์ ๋งํ๋ค.
- ๋ฏธ๋ก๋ฅผ ํ์ํ ๋, ํ ๋ฐฉํฅ์ผ๋ก ๊ฐ ์ ์์ ๋๊น์ง ๊ฐ๋ค๊ฐ ๋ ์ด์ ๊ฐ ์ ์๊ฒ ๋๋ฉด ๋ค์ ๊ฐ์ฅ ๊ฐ๊น์ด ๊ฐ๋ฆผ๊ธธ๋ก ๋์์์ ๋ค๋ฅธ ๋ฐฉํฅ์ผ๋ก ํ์์ ๋ค์ ํ๋ ๊ฒ๊ณผ ์ ์ฌ -> ์ฌ๊ท์ ๋์ผํ ํํ์ ์๊ณ ๋ฆฌ์ฆ
- ์ฆ, ๋๊ฒ ํ์ํ๊ธฐ ์ ์
๊น๊ฒ
ํ์ํ๋ ๋ฐฉ์ - ์ฌ์ฉํ๋ ๊ฒฝ์ฐ: ๋ชจ๋ ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธํ๊ณ ์ ํ๋ ๊ฒฝ์ฐ
- BFS๋ณด๋ค ์กฐ๊ธ ๋ ๊ฐ๋จํ์ง๋ง, ์๋๋ ๋๋ฆผ
DFS ํน์ง
- ์๊ธฐ ์์ ์ ํธ์ถํ๋ ์ํ(์ฌ๊ท) ์๊ณ ๋ฆฌ์ฆ์ ํํ๋ฅผ ๊ฐ๋๋ค.
์ ์ ์ํ(Pre-Order Traversals)
๋ฅผ ํฌํจํ ๋ค๋ฅธ ํํ์ ํธ๋ฆฌ ์ํ๋ ๋ชจ๋ DFS์ ํ ์ข ๋ฅ- ์ด๋ค ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธํ์๋์ง ์ฌ๋ถ๋ฅผ ๋ฐ๋์ ๊ฒ์ฌํด์ผํ๋ค. ์๊ทธ๋ฌ๋ฉด ๋ฌดํ๋ฃจํ ์ํ
- a ๋
ธ๋(๋ฃจํธ ๋
ธ๋)๋ฅผ ๋ฐฉ๋ฌธ
- ๋ฐฉ๋ฌธํ ๋ ธ๋๋ ํ์
- a์ ์ธ์ ํ ๋
ธ๋๋ค์ ์ฐจ๋ก๋ก ์ํ
- ์ธ์ ํ ๋ ธ๋๊ฐ ์์ผ๋ฉด ์ข ๋ฃ
- a์ ์ด์ํ ๋
ธ๋ b๋ฅผ ๋ฐฉ๋ฌธํ๋ค๋ฉด, a์ ์ธ์ ํ ๋ ๋ค๋ฅธ ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธํ๊ธฐ ์ ์ b์ ์ด์ ๋
ธ๋๋ค์ ์ ๋ถ ๋ฐฉ๋ฌธํด์ผ ํจ
- b๋ฅผ ๋ฃจํธ ๋ ธ๋๋ก DFS๋ฅผ ๋ค์ ์์ -> b์ ์ด์ ๋ ธ๋ ๋ฐฉ๋ฌธ
- b์ ๋ถ๊ธฐ๋ฅผ ์ ๋ถ ์๋ฒฝ ํ์ ํ๋ค๋ฉด, ๋ค์ a์ ์ธ์ ํ ์ด์ ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธํ ์ ์๋ค๋ ์๋ฏธ
- b์ ๋ถ๊ธฐ๋ฅผ ์ ๋ถ ์๋ฒฝ ํ์ํ ๋ค์์ผ a์ ๋ค๋ฅธ ์ด์ ๋ ธ๋๋ก ๊ฐ ์ ์๋ค๋ ์๋ฏธ
- ์์ง ๋ฐฉ๋ฌธ ์๋ ์ ์ ์ด ์์ผ๋ฉด ์ข ๋ฃ
- ๋ฐฉ๋ฌธ ์ํ ์ ์ด ์์ผ๋ฉด ๊ทธ ์ ์ ์์์ผ๋ก ๋ค์ DFS
DFS ๊ตฌํ
DFS์ ๊ตฌํ ๋ฐฉ์์ 2๊ฐ์ง๋ก ๋๋ ์ ์๋ค.
- ์ํ ํธ์ถ ์ฌ์ฉ
- ๋ช ์์ ์ธ ์คํ ์ฌ์ฉ: ๋ช ์์ ์ธ ์คํ์ ์ฌ์ฉํด ๋ฐฉ๋ฌธํ ์ ์ ๋ค์ ์คํ์ ์ ์ฅํ๋ค๊ฐ ๋ค์ ๊บผ๋ด์ ์์
์คํ/ํ๋ฅผ ํ์ฉํ DFS ๊ตฌํ
- ๋ฆฌ์คํธ๋ฅผ ํ์ฉํ ๊ตฌํ
def dfs(graph, start_node): ## ๊ธฐ๋ณธ์ ํญ์ ๋๊ฐ์ ๋ฆฌ์คํธ๋ฅผ ๋ณ๋๋ก ๊ด๋ฆฌํด์ฃผ๋ ๊ฒ need_visited, visited = list(), list() ## ์์ ๋ ธ๋๋ฅผ ์์ ํ๊ธฐ need_visited.append(start_node) ## ๋ง์ฝ ์์ง๋ ๋ฐฉ๋ฌธ์ด ํ์ํ ๋ ธ๋๊ฐ ์๋ค๋ฉด, while need_visited: ## ๊ทธ ์ค์์ ๊ฐ์ฅ ๋ง์ง๋ง ๋ฐ์ดํฐ๋ฅผ ์ถ์ถ (์คํ ๊ตฌ์กฐ์ ํ์ฉ) node = need_visited.pop() ## ๋ง์ฝ ๊ทธ ๋ ธ๋๊ฐ ๋ฐฉ๋ฌธํ ๋ชฉ๋ก์ ์๋ค๋ฉด if node not in visited: ## ๋ฐฉ๋ฌธํ ๋ชฉ๋ก์ ์ถ๊ฐํ๊ธฐ visited.append(node) ## ๊ทธ ๋ ธ๋์ ์ฐ๊ฒฐ๋ ๋ ธ๋๋ฅผ need_visited.extend(graph[node]) return visited
- list์์ pop์ ํ์ฉํ๋ฉด ์ฑ๋ฅ์ด ๋จ์ด์ง๋ ๋จ์
- deque๋ฅผ ํ์ฉํ ๊ตฌํ
def dfs2(graph, start_node): ## deque ํจํค์ง ๋ถ๋ฌ์ค๊ธฐ from collections import deque visited = [] need_visited = deque() ##์์ ๋ ธ๋ ์ค์ ํด์ฃผ๊ธฐ need_visited.append(start_node) ## ๋ฐฉ๋ฌธ์ด ํ์ํ ๋ฆฌ์คํธ๊ฐ ์์ง ์กด์ฌํ๋ค๋ฉด while need_visited: ## ์์ ๋ ธ๋๋ฅผ ์ง์ ํ๊ณ node = need_visited.pop() ##๋ง์ฝ ๋ฐฉ๋ฌธํ ๋ฆฌ์คํธ์ ์๋ค๋ฉด if node not in visited: ## ๋ฐฉ๋ฌธ ๋ฆฌ์คํธ์ ๋ ธ๋๋ฅผ ์ถ๊ฐ visited.append(node) ## ์ธ์ ๋ ธ๋๋ค์ ๋ฐฉ๋ฌธ ์์ ๋ฆฌ์คํธ์ ์ถ๊ฐ need_visited.extend(graph[node]) return visited
- ์คํ/ํ๋ฅผ ๊ตฌํํ ๋๋ collections ํจํค์ง์์ deque๋ฅผ ํ์ฉํ๋ ๊ฒ์ด list๋ณด๋ค ์ฑ๋ฅ์ด ๋ฐ์ด๋จ
์ฌ๊ทํจ์๋ฅผ ํตํ DFS ๊ตฌํ
def dfs_recursive(graph, start, visited = []):
## ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๋ ๋ช
๋ น์ด / ์ฌ๊ท๊ฐ ์ด๋ฃจ์ด์ง
visited.append(start)
for node in graph[start]:
if node not in visited:
dfs_recursive(graph, node, visited)
return visited
- visited ์๋ฃํ์ ๊ธฐ๋ณธ ํจ์ ์ธ์๋ก ํฌํจ์ํค๊ณ , ๋ฐฉ๋ฌธํ ๋ฆฌ์คํธ๋ค์ ์ฌ๊ท๋ฅผ ํตํด ๊ณ์ visited์ ๋ด๋ ๋ฐฉ์
์ฐธ๊ณ ์๋ฃ
DFS ์๋ฒฝ ๊ตฌํํ๊ธฐ[Python]
๋๊ธ๋จ๊ธฐ๊ธฐ