1. 그래프 : 연결되어 있는 정점과 정점 간의 관계를 표현할 수 있는 자료구조
노드(Node): 연결 관계를 가진 각 데이터를 의미한다. 정점(Vertex)이라고도 한다.
간선(Edge): 노드 간의 관계를 표시한 선.
인접 노드(Adjacent Node): 간선으로 직접 연결된 노드(또는 정점)
종류
- 유 방향 그래프: 일방통행 그래프, 각 간선은 한 방향으로만 진행할 수 있다
- 무 방향 그래프: 방향이 없는 그래프
표현 방법 ~ 여기서도 배열/링크드 리스트
인접 행렬(Adjacency Matrix): 2차원 배열로 그래프의 연결관계를 표현
인접 리스트(Adjacency List): 링크드 리스트로 그래프의 연결관계를 표현
*인접 행렬은 시간이 더 효율적이다 and 인접 리스트는 공간이 더 효율적이다
~ 실무에 대한 궁금증 : 시간이 더 효율적인 인접 행렬을 더 많이 사용할까?
2. DFS && BFS
DFS(알고리즘 깊이 우선 탐색, Depth First Search)
자료의 검색, 트리나 그래프를 탐색하는 방법. 한 노드를 시작으로 인접한 다른 노드를 재귀적으로 끝까지 탐색한 후 처음으로 복귀하여 다음 노드(단계)를 재귀적으로 탐색
BFS(알고리즘 너비 우선 탐색, Breath First Search)
시작 노드를 줌심으로 인접한 모든 노드를 우선 탐색한 후 다음 노드(단계)를 탐색하는 방법
DFS, BFS의 대표적인 사례: 알파고
DFS: 그래프의 최대 깊이만큼의 공간을 요구하므로 공간 사용량이 적으나, 최단 경로를 찾기 어렵다
DFS 구현 : 재귀함수
graph = {
1: [2, 5, 9],
2: [1, 3],
3: [2, 4],
4: [3],
5: [1, 6, 8],
6: [5, 7],
7: [6],
8: [5],
9: [1, 10],
10: [9]
}
visited = []
#1. 시작 노드(루트 노드)인 1부터 탐색합니다.
#2. 현재 방문한 노드를 visited_array에 추가합니다.
#3. 현재 방문한 노드와 인접한 노드 중 방문하지 않은 노드에 방문합니다.
#visited_array = [1]
def dfs_recursion(adjacent_graph, cur_node, visited_array):
visited_array.append(cur_node)
for adjacent_node in adjacent_graph:
if adjacent_node not in visited_array: #탈출 조건: 탐색을 했다면 추가하지 않는다
dfs_recursion(adjacent_graph, adjacent_node, visited_array)
return
dfs_recursion(graph, 1, visited) # 1 이 시작노드입니다!
print(visited) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 이 출력되어야 합니다!
DFS 구현 : 스택 **VS BFS = DFS vs BFS : 스택 VS 큐
def dfs_stack(adjacent_graph, start_node):
stack = [start_node]
visited = []
while stack:
current_node = stack.pop()
visited.append(current_node)
for adjacent_node in adjacent_graph[current_node]:
if adjacent_node not in visited:
stack.append(adjacent_node)
return visited
print(dfs_stack(graph, 1)) # 1 이 시작노드입니다!
# [1, 9, 10, 5, 8, 6, 7, 2, 3, 4] 이 출력되어야 합니다!
BFS: 모든 인접 노드를 우선 탐색하므로 최단 경로를 쉽게 파악할 수 있다. 그러나 모든 인접 노드와 경로를 파악해야 하므로 시간 및 공간 사용량이 많다
BFS 구현 : 큐 **VS DFS = DFS vs BFS : 스택 VS 큐
graph = {
1: [2, 3, 4],
2: [1, 5],
3: [1, 6, 7],
4: [1, 8],
5: [2, 9],
6: [3, 10],
7: [3],
8: [4],
9: [5],
10: [6]
}
def bfs_queue(adj_graph, start_node):
queue = [start_node]
visited = []
while queue:
current_node = queue.pop(0)
visited.append(current_node)
for adjacent_node in adj_graph[current_node]:
if adjacent_node not in visited:
queue.append(adjacent_node)
return visited
print(bfs_queue(graph, 1)) # 1 이 시작노드입니다!
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 이 출력되어야 합니다!
'개발공부 > 알고리즘🔐' 카테고리의 다른 글
프로그래머스 Lv 0 : 더 크게 합치기 (0) | 2023.07.18 |
---|---|
[JAVA] 형 변환 유형 : 문자열 -> 정수 (0) | 2022.12.08 |
문제해결 연습(1): 알고리즘과 친해지기 w.파이썬 (0) | 2022.11.15 |
11.10 알고리즘 강의: 링크드 리스트 구현(2) 및 재귀 함수 (0) | 2022.11.11 |