DFS/BFS - 그래프 탐색 알고리즘
스택 자료구조 - 선입후출, 입구와 출구가 동일한 형태, 박스 쌓고 내린다고 생각하면 됨
-> 삽입하고 삭제하는 방식
stack = []
stack.append(5)
stack.append(2)
stack.append(3)
stack.append(7)
stack.pop()
stack.append(1)
stack.append(4)
stack.pop()
print(stack[::-1])
print(stack[::])
큐 자료구조 - 선입선출, 입구와 출구가 모두 있는 터널, 은행 대기표/편의점 우유 생각하면 됨
리스트로 구현은 가능한데 시각복잡도가 높아서 비효율적이라 덱 라이브러리를 꼭 사용
from collections import deque
queue = deque()
queue.append(5)
queue.append(2)
queue.append(3)
queue.append(7)
queue.popleft()
queue.append(1)
queue.append(4)
queue.popleft()
print(queue)
queue.reverse()
print(queue)
재귀 함수 - DFS 에서 자주 사용, 파이썬에서 최대 재귀 깊이 제한이 있어서 오류 메세지가 나올 수 있음
종료 조건 : 100번째 호출을 했을 때 종료되도록 종료 조건 명시
-모든 재귀함수는 반복문을 이용하여 동일한 기능을 구현할 수 있다.(유리할 때도 있고 불리할 때도 있음)
-컴퓨터가 함수를 연속적으로 호출하면 컴퓨터 메모리 내부의 스택 프레임에 쌓여서 스택 라이브러리 대신 재귀함수를 이용하는 경우가 많다.
def recursive_function(i):
if i == 100:
return
print(i, '번째 재귀함수에서', i+1,'번째 재귀함수를 호출합니다')
recursive_function(i+1)
print(i,'번째 재귀함수를 종료합니다.')
recursive_function(1)
재귀 함수 예제1 - 팩토리얼 예제, 0! = 1
def factorial_recursive(n):
if n <= 1:
return 1
return n*factorial_recursive(n-1)
print(factorial_recursive(5))
재귀 함수 예제2 - 유클리드 호제법(최대공약수 계산)
def gcd(a,b):
if a % b == 0:
return b
else:
return gcd(b, a % b)
print(gcd(192,162))
DFS 알고리즘 - 깊이 우선 탐색, 스택 자료구조(or 재귀 함수)
- 탐색 시작 노드를 스택에 삽입하고 방문 처리함
- 스택의 최상단 노드에 방문하지 않은 노드가 하나라도 있으면 그 노드를 스택에 넣고 방문 처리한다. 방문하지 않은 인접 노드가 없으면 스택에서 최상단 노드를 꺼낸다.
- 더이상 2번의 과정을 수행할 수 없을 때까지 반복한다.
DFS 메서드 정의
def dfs(graph, v, visited):
visited[v] = True
print(v, end = '')
for i in graph[v]:
if not visited[i]:
dfs(graph, i, visited)
graph = [
[],
[2,3,8],
[1,7],
[1,4,5],
[3,5],
[3,4],
[7],
[2,6,8],
[1,7]
]
visited = [False]*9
dfs(graph, 1, visited)
BFS 알고리즘 - 너비 우선 탐색, 가까운 노드부터 우선적으로 탐색, 큐 자료 구조
- 탐색 시작 노드를 큐에 삽입하고 방문 처리함
- 큐에서 노드를 꺼낸 뒤에 해당 노드의 인접 노드 중에서 방문하지 않은 노드를 모두 큐에 삽입하고 방문 처리한다.
- 더이상 2번의 과정을 수행할 수 없을 때까지 반복한다.
from collections import deque
def bfs(graph,start,visited):
queue = deque([start])
visited[start] = True
while queue:
v = queue.popleft()
print(v,end = '')
for i in graph[v]:
if not visited[i]:
queue.append(i)
visited[i] = True
graph = [
[],
[2,3,8],
[1,7],
[1,4,5],
[3,5],
[3,4],
[7],
[2,6,8],
[1,7]
]
visited = [False]*9
bfs(graph,1,visited)
문제1. 음료수 얼려먹기 (DFS or BFS, 그래프 형태로 모델링할 수 있으므로)
n,m = map(int,input().split())
graph = []
for i in range(n):
graph.append(list(map(int,input())))
def dfs(x,y):
if x <= -1 or x >= n or y <= -1 or y >= m:
return False
if graph[x][y] == 0:
graph[x][y] = 1
dfs(x-1, y)
dfs(x+1, y)
dfs(x, y-1)
dfs(x, y+1)
return True
return False
result = 0
for i in range(n):
for j in range(m):
if dfs(i,j) == True:
result += 1
print(result)
문제2. 미로 탈출 - BFS
from collections import deque
n,m = map(int,input().split())
graph = []
for i in range(n):
graph.append(list(map(int,input())))
dx = [-1,1,0,0]
dy = [0,0,-1,1]
def bfs(x,y):
queue = deque()
queue.append((x,y))
while queue:
x,y = queue.popleft()
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if nx < 0 or nx >= n or ny < 0 or ny >= m:
continue
if graph[nx][ny] == 0:
continue
if graph[nx][ny] == 1:
graph[nx][ny] = graph[x][y] + 1
queue.append((nx,ny))
return graph[n-1][m-1]
print(bfs(0,0))