❗ X축과 Y축을 가지고 있는 그래프가 아니다!
그래프에 대해 설명 후, 너비 우선 탐색 알고리즘을 배운다.
너비 우선 탐색은 매우 유용한 알고리즘이다.
: 연결의 집합을 모형화한 것.
그래프는 항목들이 서로 어떻게 연결되어 있는지를 모형화하는 방법이다.
ⓐ→ⓑ
ⓐ
, ⓑ
)→
또는 -
)→
로 이어짐 : 화살표 방향으로 관계를 가짐-
로 이어짐 : 상호 관계를 나타냄: 그래프를 대상으로 하는 탐색 알고리즘.
너비 우선 탐색을 통해 아래의 두 질문에 대답할 수 있다.
예제 : 망고 판매상 찾기. (134페이지부터)
나는 망고 농사를 짓고 있고, 망고를 팔아 줄 사람을 찾아야 한다.
내 친구(1촌) 중에 망고 판매상이 있는지 알아본다.
없다면 내 친구의 친구(2촌) 중에 망고 판매상이 있는지 알아본다.
...
망고 판매상을 찾을때까지 모든 친구들을 찾는다.
버스 정류장에 줄을 설 때와 같은 원리. 먼저 줄을 선 사람부터 버스에 탈 수 있다.
즉 반드시 먼저 추가된 사람들을 먼저 꺼내서 탐색하는 자료구조.
큐(선입선출, FIFO) <->
스택(후입선출, LIFO, Last In First Out)
가장 먼저 코드로 그래프를 구현해야 함 - 해시테이블(맵)을 활용.
키 : 노드
값 : 그 노드가 이웃한 노드
예를 들어 내 친구가 앨리스, 밥, 클레어라면
{앨리스, 밥, 클레어}
배열.클레어의 친구가 톰, 조니라면
{톰, 조니}
배열.graph = {}
graph["you"] = ["alice", "bob", "claire"]
graph["bob"] = ["anuj", "peggy"]
graph["alice"] = ["peggy"]
graph["clair"] = ["thom", "jonny"]
graph["anuj"] = []
graph["peggy"] = []
graph["thom"] = []
graph["jonny"] = []
너비 우선 탐색 알고리즘의 과정은 다음과 같다
(망고 판매상 찾기 예제에서)
(아래는 파이썬 구현 코드 - 양방향 큐인 deque 사용)
from collections import deque
def search(name):
search_queue = deque() ## 큐 (탐색 목록)
search_queue += graph[name] ## name의 모든 1촌을 큐에 추가
searched = [] ## 이미 확인한 사람을 추적하기 위한 배열
while search_queue: ## 큐가 비어있지 않은 한 계속 실행
person = search_queue.popleft()
if not person in searched:
if person_is_seller(person):
print person + " is a mango seller!"
return True
else:
search_queue += graph[serson] ## 망고 판매상이 아니라면, 그 사람의 이웃들을 큐에 추가
searched.append(person)
return False ## 여기까지 도달했다면 망고 판매상이 아무도 없음을 뜻함
def person_is_seller(name):
return name[-1] == 'm' ## 사람 이름이 m으로 끝난다면 망고 판매상이라고 판단
너비 우선 탐색 알고리즘이 종료되는 경우
확인한 사람을 추적하는 이유?
peggy
처럼). 서로 참조하는 관계에 있을 때 서로가 서로를 큐에 추가하며 무한반복에 빠지게 됨.너비 탐색 알고리즘 = 그래프의 모든 정점을 따라 움직임.
O(간선의 갯수)
.큐에 탐색할 사람을 추가하는 데에는 상수 시간인 O(1)
이 걸림.
O(사람의 수)
이 걸림결론 : 너비 우선 탐색은 O(사람의 수 + 간선의 수)
의 실행시간을 가짐
O(V+E)
라고 표기V
= 정점의 수E
= 간선의 수