2024. 1. 29. 02:29ใCS - Roadmap.sh/3. Common Algorithms
CS - 3. Common Algorithms - 3.5 Graph - 3.5.2 Depth First Search(DFS)
Depth First Search
๐กDepth first search is a graph traversal algorithm that starts at a root node and explores as far as possible along each branch before backtracking.
๊น์ด ์ฐ์ ๊ฒ์์ ๋ฃจํธ ๋ ธ๋์์ ์์ํ์ฌ ๊ฐ ๋ถ๊ธฐ๋ฅผ ๋ฐ๋ผ ๊ฐ๋ฅํ ํ ๋ฉ๋ฆฌ ํ์ํ ํ ์ญ์ถ์ ํ๋ ๊ทธ๋ํ ํ์ ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค.
๋จผ์ , ๊น์ด ์ฐ์ ํ์(Depth First Search, DFS)์ ๋ํด ์ค๋ช
๋๋ฆฌ๊ฒ ์ต๋๋ค.
DFS๋ ๋ฃจํธ ๋
ธ๋(ํน์ ๋ค๋ฅธ ์์์ ๋
ธ๋)์์ ์์ํด์ ๋ค์ ๋ถ๊ธฐ(branch)๋ก ๋์ด๊ฐ๊ธฐ ์ ์ ํด๋น ๋ถ๊ธฐ๋ฅผ ์๋ฒฝํ๊ฒ ํ์ํ๋ ์๊ณ ๋ฆฌ์ฆ์
๋๋ค. ๋ฐ์ดํฐ์ ๊ตฌ์กฐ๊ฐ ํธ๋ฆฌ ํน์ ๊ทธ๋ํ ํํ์ผ ๋ ์ฌ์ฉํ๋ฉฐ, ๋ชจ๋ ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธํ๊ณ ์ ํ๋ ๊ฒฝ์ฐ์ ์ด ๋ฐฉ๋ฒ์ ์ ํํฉ๋๋ค.
DFS์ ๋์ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค
1. ๋ฃจํธ ๋
ธ๋๋ฅผ ์คํ์ ๋ฃ์ต๋๋ค.
2. ํ์ฌ ์คํ์ ๋งจ ์ ๋
ธ๋๋ฅผ ํ์ธํฉ๋๋ค.
3. ํ์ฌ ๋
ธ๋์ ๋ฐฉ๋ฌธํ์ง ์์ ์ธ์ ๋
ธ๋๊ฐ ์์ผ๋ฉด ๊ทธ ๋
ธ๋๋ฅผ ์คํ์ ๋ฃ๊ณ ๋ฐฉ๋ฌธ์ฒ๋ฆฌ๋ฅผ ํฉ๋๋ค. ๋ฐฉ๋ฌธํ์ง ์์ ์ธ์ ๋
ธ๋๊ฐ ์์ผ๋ฉด ์คํ์์ ๋งจ ์ ๋
ธ๋๋ฅผ ๊บผ๋
๋๋ค.
4. ๋ ์ด์ 2๋ฒ์ ๊ณผ์ ์ ์งํํ ์ ์์ ๋๊น์ง ๋ฐ๋ณตํฉ๋๋ค.
์ฃผ์์ ์ ๊น์ด๊ฐ ๋ฌดํ๋๊ฐ ๋ ๋์ด๋ค. ํนํ ๋ฃจํ(ํ๋ก)๊ฐ ์๋๊ฒฝ์ฐ DFS๋ ์ฃ์ง๋ฅผ ํ์ถํ ์ ์๊ฒ ๋๋ค.
๊น์ด๊ฐ ์์ฃผ ๊น์ด๋ ์คํ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก ์ฃผ์ํด์ผํ๋ค.
In Python
DFS๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์๋ ์คํ๋ฐฐ์ด๊ณผ ์ฌ๊ท(3.2. Recursion)๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค.
3.5.2.1 DFS - ์คํ๋ฐฐ์ด๋ก ๊ตฌํํ๊ธฐ
def DFS(graph, root):
visited = []
stack = [root]
while stack:
n = stack.pop()
if n not in visited:
visited.append(n)
stack += graph[n] - set(visited)
return visited
๋ฆฌ์คํธ์ set() ๊ฐ์ - ์ฐ์ฐ์ด ์ง์๋์ง ์๋๋ค. ์์ ํจ์์์ stack += graph[n] - set(visted) ์์
graph ๋ set()์ ์์์ฃผ๋ฉด ๋๋ค.
def DFS(graph, root):
visited = []
stack = [root]
while stack:
n = stack.pop()
if n not in visited:
visited.append(n)
stack += set(graph[n]) - set(visited)
# print("graph : ", set(graph[n]), "visited : ", set(visited) ) # ์ ์ฐจ ๋ณด์ฌ์ฃผ๊ธฐ
return visited
DFS ๋๋ก ์ ๋ณด์ธ๋ค.
์์ฅ์์ ๊ทธ๋ํ๋ฅผ ์๊ฐํ ํ๋ ์ฝ๋๋ฅผ ์ด์ฉํด์ ์๊ฐํ ํด๋ณด๋ฉด ์ด๋ ๋ค.
1 - 2,3 ์ด ์๋๋ฐ
์์ ํจ์๋ ์์ ๋ ธ๋์์ ๊ฐ์ฅ ๋ฉ๋ฆฌ ์๋ ๋ ธ๋๋ถํฐ ๋ฐฉ๋ฌธํ๊ฒ ๋๋ค. (1-3-6)
๊ทธ๋ฐ ์์๋๋ก 1-2-5-7, 1-2-4 ๋ฅผ ๋ฐฉ๋ฌธํ๊ฒ ๋๋ค.
์ง๊ธ ์์ ํจ์์๋ ์ด์ง ์ค๋ฅ๊ฐ์๋๋ฐ,
์๋๋ผ๋ฉด 1-2,3 ์์ ์์ ๋ ธ๋ ์์๋๋ก ๋ฐฉ๋ฌธํด์ผ ํ๋๋ฐ, pop()์ ์ฌ์ฉํด์ {2,3}์์ ์ ์ผ ๋ค์ 3๋ถํฐ ๋ฐฉ๋ฌธํ๊ฒ ๋์๋ค.
( pop()์ ์ฌ์ฉํ ์ด์ ๋ ์๊ฐ ๋ณต์ก๋๊ฐ O(1) ์ด๊ธฐ ๋๋ฌธ์ด๋ค. pop(0)์ ์ฌ์ฉํ๊ฒ๋๋ฉด ๊ฐ์ฅ ์์ ์์๋ฅผ ์ ๊ฑฐํ๊ณ ๋ฐํํ์ง๋ง ๋ฆฌ์คํธ์ ๋ชจ๋ ์์๋ฅผ ํ์นธ์ฉ ์ด๋์์ผ์ผํ๋ฏ๋ก ์๊ฐ ๋ณต์ก๋๊ฐ O(n) ์ด ๋๋ค.)
pop(0)์ ์ฌ์ฉํด ์ ๋๋ก DFS๋ฅผ ๋ง๋ ๋ค๋ฉด,
def DFS_pop0(graph, root):
visited = []
stack = [root]
while stack:
n = stack.pop(0) # pop(0)์ ์ฌ์ฉํ์ฌ ์คํ์ ์ฒซ ๋ฒ์งธ ์์๋ฅผ ์ถ์ถ
if n not in visited:
visited.append(n)
stack = list(set(graph[n]) - set(visited)) + stack # stack์ ์์ชฝ์ ์์ง ๋ฐฉ๋ฌธํ์ง ์์ ๋
ธ๋๋ฅผ ์ถ๊ฐ
# print("graph : ", set(graph[n]), "visited : ", set(visited) )
return visited
์ ๋๋ก 1-2,3 ์์ 2 ๋ ธ๋๋ถํฐ ํ์์ ํ๊ฒ ๋์๋ค.
3.5.2.2 DFS - ์ฌ๊ทํธ์ถ๋ก ๊ตฌํํ๊ธฐ
def dfs_recursion(graph: dict, start: int):
visited = {node: False for node in graph.keys()}
result = [] # ๋ฐฉ๋ฌธํ ๋
ธ๋๋ฅผ ์ ์ฅํ ๋ฆฌ์คํธ
def search(current: int):
visited[current] = True
result.append(current) # ๋ฐฉ๋ฌธํ ๋
ธ๋๋ฅผ result์ ์ถ๊ฐ
for next_node in graph[current]:
if not visited[next_node]:
search(next_node)
search(start)
return result # ๋ฐฉ๋ฌธํ ๋
ธ๋์ ์์๋ฅผ ๋ฐํ
search ํจ์ ๋ด์์ search(next_node)๋ก ์ฌ๊ท ํธ์ถ๋ก์จ ๊ตฌํํ๋ค.
ํ์ฌ ๋ ธ๋์ ์ธ์ ๋ ธ๋๋ค ์ค ์์ง ๋ฐฉ๋ฌธํ์ง ์์ ๋ ธ๋๊ฐ ์๋ค๋ฉด, ๊ทธ ๋ ธ๋๋ฅผ ๋ค์ search ํจ์์ ์ธ์๋ก ๋ฃ์ด์ ํจ์๋ฅผ ํธ์ถํ๋ค.
BFS ์ DFS
๋ฐฑํธ๋ํน(Backtracking).
๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ์ ๋ถ ๊ณ ๋ คํ๋ ์๊ณ ๋ฆฌ์ฆ ์ ์ ํฉํ ๋ฐฉ์๋ค์ด๋ค.
๊ฒฝ์ฐ์ ๋ฐ๋ผ ๋ค๋ฅด์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก ๊ฒฝ์ฐ์ ์์์๋ DFS๊ฐ ์ ๋ฆฌํ๋ค.
1. ๋ชจ๋ ๊ฐ๋ฅ์ฑ ํ์
- DFS ๋ ํ๋ฐฉํฅ์ผ๋ก ๋๊น์ง ํ์ํ ํ ๋ค๋ฅธ ๋ฐฉํฅ์ผ๋ก ํ์์ ์งํํ๊ธฐ์ ๋ฐฑํธ๋ํน ๋ฌธ์ ์ธ ๋ชจ๋ ๊ฐ๋ฅ์ฑ์ ํ์ํ๋๋ฐ ์ ๋ฆฌํ.
2. ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ
- BFS๋ ํ๋ฅผ ์ฌ์ฉํด ๋ชจ๋ ๋ ธ๋๋ฅผ ์ ์ฅํ๋ค.
๋ฐ๋ฉด DFS๋ ์คํ์ ์ฌ์ฉํด ํ์ฌ ๊ฒฝ๋ก์์ ๋ ธ๋๋ง์ ์ ์ฅํ๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ ๋ค.
3. ํด๋ต ๋๋ฌ ์ ๋น ๋ฅธ ์ข ๋ฃ
- DFS๋ ํด๋ต์ ๋๋ฌํ๋ฉด ์ฆ์ ํ์์ ์ข ๋ฃํ ์ ์๋ค.
๋ฐ๋ฉด BFS๋ ๋ชจ๋ ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธํด์ผ ํ๋ฏ๋ก ์ข ๋ฃ ์์ ์ด ๋ฆ์ด์ง ์ ์๋ค.
DFS ์ฌ์ฉ์ ์ฃผ์ํด์ผ ํ ์ ์ ์์ฃผ ์น๋ช ์ ์ธ ์ค๋ฅ๋ฅผ ๋ฐ์์ํค๋ฏ๋ก ์์์๋ ๋ค๋ค์๋ค.
๋ค์ ์ ๋ฆฌํด๋ณด์๋ฉด,
1. ๋ฌดํ ๋ฃจํ
- DFS๋ ์ฌ๊ท ํธ์ถ์ ์ฌ์ฉํ๋ฏ๋ก, ์๋ชป ๊ตฌํ์ ๋ฌดํ ๋ฃจํ์ ๋น ์ง ์ ์๋ค.
๋ฐ๋ผ์ ๋ฐฉ๋ฌธํ ๋ ธ๋๋ฅผ ์ฒดํฌํด์ผ ํ๋ฉฐ, ์ฌ๊ท ํธ์ถ์ ์ข ๋ฃ ์กฐ๊ฑด์ ๋ช ํํ ์ค์ ํด์ผ ํ๋ค.
2. ์คํ ์ค๋ฒํ๋ก์ฐ
- ์ฌ๊ท ํธ์ถ์ ๊น์ด๊ฐ ๋๋ฌด ๊น์ด์ง๋ฉด ์คํ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ๋ค.
์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ์ํด ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ DFS ๊ตฌํ์ ๊ณ ๋ คํ ์ ๋ ์๋ค.
'CS - Roadmap.sh > 3. Common Algorithms' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
3.5 Graph - 3.5.4 Dijkstraโs Algorithm (2) | 2024.01.30 |
---|---|
3.5 Graph - 3.5.3 Bellman Fordโs Algorithm (1) | 2024.01.29 |
3.5 Graph - 3.5.1 Breadth First Search(BFS) (0) | 2024.01.28 |
3.5 Graph & 3.6 Tree (0) | 2024.01.27 |
3.4. Cache - 3.4.3 MFU Cache (0) | 2024.01.27 |