BFS зазвичай описується приблизно так (з Вікіпедії ).
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|+|E|)
Чи можемо ми уникнути наявності структури даних із часом ініціалізації ? Нашою першою спробою може бути використання пов'язаного списку. Однак зараз тестування, чи була виявлена вершина (рядок 10), займає лінійний час у кількості відвідуваних вершин, а не постійний час, як раніше. Це означає, що час роботи стає , що в гіршому випадку набагато гірше. (Зверніть увагу, що ми не хочемо переписувати це як оскільки це ще гірше: це може бути так само погано, як , тоді як )Θ(|V|)O(|V||E|)O(|E|2)|V|4|V||E|≤|V|3
Використання масиву, що динамічно змінюється, дозволить нам вести список впорядкованим, тож тепер пошуки потребують лише часу але це все ще дає час роботи лише , що ще гірше, ніж стандарт.O(log|V|)O(|E|log|V|)
Нарешті, ми могли б використовувати хеш-таблицю з динамічним розміром: починати з таблиці постійного розміру і подвоювати її щоразу, коли вона стає наповнена. Це означає, що кінцевий розмір таблиці становить щонайбільше вдвічі більше вершин, виявлених до закінчення алгоритму, і це щонайбільше оскільки ми ніколи не виявляємо нічого поза складовою вершини початку. Крім того, загальний обсяг виконаної роботи з копіювання хеш-таблиці для її розширення становить не більше. Пошуки та вставки до хеш-таблиці амортизуються тому ми дійсно отримуємо час роботи .c|E|+1c+2c+4c+⋯+2|E|≤4|E| O(1)O(|E|)
Так можливо, але хотіли б це зробити в реальній реалізації? Я б сказав, мабуть, ні. Якщо у вас немає підстав вважати, що ваші вхідні графіки матимуть безліч дрібних компонентів, накладні витрати на підтримку хеш-таблиці додадуть помітний постійний коефіцієнт до часу виконання. Вирощування хеш-таблиці може зайняти часі пошук буде вимагати, щоб ви обчислили хеш-функцію і, в середньому, переглянули більше одного слота в таблиці. Незадовільна кеш-пам'ять хеш-таблиць також може завдати шкоди справжньому комп'ютеру. У більшості випадків при застосуванні стандартного масиву частина є домінуючим членомO(|E|)4|E|O(|E|)O(|V|+|E|) час роботи, тому не варто використовувати хеш-таблицю, щоб видалити домінуючий термін, враховуючи практичну вартість цього.