너비 우선 검색이 제 시간에 실행되는 이유


9

그래프 에서 너비 우선 탐색 (BFS)의 실행 시간 이 라고 종종 언급됩니다 (예 : Wikipedia . 그러나 연결된 그래프에는 있으며 연결되지 않은 그래프에서도 BFS는 시작 정점을 포함하는 구성 요소 외부의 정점을 절대로 보지 않습니다. 해당 구성 요소에는 최대 모서리를 포함하므로 최대 정점이 포함되며 알고리즘이 방문 할 유일한 정점입니다.=(V,이자형)영형(|V|+|이자형|)|V||이자형|+1|이자형||이자형|+1

이것은 이므로 실행 시간이 단지 라고 말하지 않겠습니까?|V|+|이자형|2|이자형|+1영형(|이자형|)

이것은 Disjkstra의 알고리즘 실행 시간에 관한 질문에 대한 의견으로 나타났습니다 .


왜 시작 정점이 있다고 가정합니까? 예를 들어 최대 일치 문제의 BFS는 hopcroft karp 알고리즘의 모든 일치하지 않는 정점에서 시작합니다. 이 경우, 주어진 그래프가 많은 연결된 구성 요소의 숲이라면 우리는
edger

2
@narekBojikian BFS는 다양한 방법으로 사용될 수 있지만 독립형 알고리즘으로 제시 될 때는 항상 시작 정점이 있습니다.
David Richerby

답변:


9

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| 과 |이자형| 우리는 러닝 타임을 얻는다 영형(|V|+|이자형|).

데이터 구조를 피할 수 있습니까? Θ(|V|)초기화 시간? 첫 번째 시도는 링크 된 목록을 사용하는 것입니다. 그러나 이제 정점이 발견되었는지 테스트하면 (10 행) 이전과 같이 일정 시간이 아닌 방문한 정점 수에서 선형으로 시간이 걸립니다. 이것은 러닝 타임이영형(|V||이자형|)최악의 경우 훨씬 더 나쁩니다. (우리는 그것을 다음과 같이 다시 쓰고 싶지 않습니다.영형(|이자형|2) 그것은 더 나쁘기 때문에 : 그것은만큼 나쁠 수 있습니다. |V|4반면에 |V||이자형||V|.)

동적으로 크기가 조정 된 배열을 사용하면 목록을 정렬 된 상태로 유지할 수 있으므로 조회에는 시간이 걸립니다. 영형(로그|V|) 그러나 그것은 여전히 ​​실행 시간을 제공합니다 영형(|이자형|로그|V|)여전히 표준보다 나쁩니다.

마지막으로 동적 크기의 해시 테이블을 사용할 수 있습니다. 일정한 크기의 테이블로 시작하십시오. 반이 가득 찰 때마다 두 배로 늘립니다. 즉, 테이블의 최종 크기는 알고리즘이 종료되기 전에 발견되는 정점 수의 최대 두 배이며 최대 크기입니다.|이자형|+1시작 정점의 구성 요소 외부에서는 아무것도 발견하지 못하기 때문입니다. 또한 해시 테이블을 복사하여 확장 한 총 작업량은 최대입니다.+2+4++2|이자형|4|이자형|. 해시 테이블에 대한 조회 및 삽입이 상각됩니다. 영형(1) 그래서 우리는 실제로 러닝 타임을 얻습니다. 영형(|이자형|).

그래서 O(|E|)가능하지만 실제 구현에서 그렇게하고 싶습니까? 아마 그렇지 않을 것입니다. 입력 그래프에 많은 작은 구성 요소가 있다고 생각하지 않는 한 해시 테이블을 유지 관리하는 오버 헤드로 인해 실행 시간에 눈에 띄는 일정한 요소가 추가됩니다. 해시 테이블을 성장시키는 데 시간이 걸릴 수 있습니다4|E|조회는 해시 함수를 계산하고 평균적으로 테이블에서 둘 이상의 슬롯을 확인해야합니다. 해시 테이블의 캐시 성능이 좋지 않으면 실제 컴퓨터에서 손상을 입을 수도 있습니다. 대부분의 경우 표준 배열 구현에서는O(|E|) 부분은의 지배적 인 용어입니다 O(|V|+|E|) 실행 시간이 많기 때문에 해시 테이블을 사용하여 지배적 인 용어를 제거하는 것은 가치가 없습니다.


1
실제로 해시 테이블의 캐시 성능이 좋지 않다고 주장하기에는 너무 강할 수 있습니다. 연결 (예 : 연결 목록)로 구현하면 동의합니다. 그러나 지속적인 메모리 덩어리와 개방형 주소 지정으로 구현한다면 그렇게 많지 않습니다.
Juho

정말 멋진 답변입니다! 그러나 작은 크기의 해시 테이블은 작은 구성 요소가 많을 때뿐만 아니라 모든 정점의 해시 값이 합리적인 상수로 제한되어 있으며 종종 발생하는 경우 실제로 좋은 선택입니다. 좋은 답변!
카를로스 리나 레스 로페즈

1
데이비드, 나는 몇 년 전에 비슷한 생각을했습니다. 나는 그 대답이 역사적 관점에 있다고 생각합니다.
kelalaka
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.