BFS는 일반적으로 다음과 같습니다 ( Wikipedia에서 ).
1 procedure BFS(G,start_v):
2 let Q be a queue
3 label start_v as discovered
4 Q.enqueue(start_v)
5 while Q is not empty
6 v = Q.dequeue()
7 if v is the goal:
8 return v
9 for all edges from v to w in G.adjacentEdges(v) do
10 if w is not labeled as discovered:
11 label w as discovered
12 w.parent = v
13 Q.enqueue(w)
이 문제는 다소 미묘한 문제입니다. 3 행에 숨어 있습니다! 문제는 어떤 정점이 발견되었는지 저장하기 위해 어떤 데이터 구조를 사용할 것인가입니다.
가장 간단한 해결책은 꼭짓점 당 하나의 항목으로 부울 배열을 사용하는 것입니다. 이 경우 배열의 모든 요소를 초기화해야 false
하며 시간이 걸립니다.Θ(|V|). 이것은 모서리가 전혀 없어도 모든 그래프에 적용되므로 관계를 가정 할 수 없습니다|V| 과 |E| 우리는 러닝 타임을 얻는다 O ( | V| + | 이자형| ).
데이터 구조를 피할 수 있습니까? Θ ( | V| )초기화 시간? 첫 번째 시도는 링크 된 목록을 사용하는 것입니다. 그러나 이제 정점이 발견되었는지 테스트하면 (10 행) 이전과 같이 일정 시간이 아닌 방문한 정점 수에서 선형으로 시간이 걸립니다. 이것은 러닝 타임이O ( | V|| 이자형| )최악의 경우 훨씬 더 나쁩니다. (우리는 그것을 다음과 같이 다시 쓰고 싶지 않습니다.O ( | E|2) 그것은 더 나쁘기 때문에 : 그것은만큼 나쁠 수 있습니다. | V|4반면에 | V|| 이자형| ≤ | V|삼.)
동적으로 크기가 조정 된 배열을 사용하면 목록을 정렬 된 상태로 유지할 수 있으므로 조회에는 시간이 걸립니다. O ( 로그| V| ) 그러나 그것은 여전히 실행 시간을 제공합니다 O ( | E| 로그| V| )여전히 표준보다 나쁩니다.
마지막으로 동적 크기의 해시 테이블을 사용할 수 있습니다. 일정한 크기의 테이블로 시작하십시오. 씨반이 가득 찰 때마다 두 배로 늘립니다. 즉, 테이블의 최종 크기는 알고리즘이 종료되기 전에 발견되는 정점 수의 최대 두 배이며 최대 크기입니다.| 이자형| +1시작 정점의 구성 요소 외부에서는 아무것도 발견하지 못하기 때문입니다. 또한 해시 테이블을 복사하여 확장 한 총 작업량은 최대입니다.c + 2 c + 4 c + ⋯ + 2 | 이자형| ≤4 | 이자형|. 해시 테이블에 대한 조회 및 삽입이 상각됩니다. O ( 1 ) 그래서 우리는 실제로 러닝 타임을 얻습니다. O ( | E| ).
그래서 O ( | E| )가능하지만 실제 구현에서 그렇게하고 싶습니까? 아마 그렇지 않을 것입니다. 입력 그래프에 많은 작은 구성 요소가 있다고 생각하지 않는 한 해시 테이블을 유지 관리하는 오버 헤드로 인해 실행 시간에 눈에 띄는 일정한 요소가 추가됩니다. 해시 테이블을 성장시키는 데 시간이 걸릴 수 있습니다4 | 이자형|조회는 해시 함수를 계산하고 평균적으로 테이블에서 둘 이상의 슬롯을 확인해야합니다. 해시 테이블의 캐시 성능이 좋지 않으면 실제 컴퓨터에서 손상을 입을 수도 있습니다. 대부분의 경우 표준 배열 구현에서는O ( | E| ) 부분은의 지배적 인 용어입니다 O ( | V| + | 이자형| ) 실행 시간이 많기 때문에 해시 테이블을 사용하여 지배적 인 용어를 제거하는 것은 가치가 없습니다.