В этой статье я объясню концепции BFS, DFS и других важных алгоритмов в компьютерном программировании.
Это обязательные навыки для каждого студента, изучающего информатику.
Узлы и ребра

Для любого графа G = (V, E), где:
- V: набор узлов (вершин). Иногда также обозначается n.
- E: набор ребер между парами узлов. Иногда также обозначается m.
Для неориентированных графов:
- deg(v) = Количество ребер в v
- ∑v∈V град(v) = 2E
Для ориентированных графов:
- deg_in(v) = количество ребер, входящих в v
- deg_out(v) = Количество ребер, выходящих из v
- ∑v∈V deg_out(v) = ∑v∈V deg_in(v) = E
Путь, связность, цикл, расстояние и дерево
Определение: Путь — это последовательность узлов от v1 до vn, такая, что каждый (vi, v(i+1)) является ребром. Количество ребер пути называется длиной.
По определению: путь называется простым, если все узлы различны.
По определению: неориентированный граф связен, если для любых узлов u и v между ними существует путь.
По определению: цикл — это путь, где v1 и vn — одни и те же узлы. Если все узлы от v1 до v(n-1) различны, такой цикл простой.
По определению: Длина кратчайшего простого пути между двумя узлами называется расстоянием между двумя узлами.
Определение: неориентированный граф является лесом, если он не содержит цикла. Кроме того, если такой граф связен, то это дерево.
BFS — поиск в ширину
Сценарий: предположим, что есть связный неориентированный граф, и для данного узла s мы хотим обозначить расстояние между s и каждым из остальных узлов в графе.
Следовательно, мы можем обозначить расстояние «слой за слоем». Мы бы обозначили расстояние 1 для первого слоя, 2 для второго слоя и так далее. Это называется «поиск в ширину».
См. псевдокод ниже:
BFS(G,s):
# Setting up the initial value for each node
for each vertex u∈V - {s}
# White for undiscovered
# gray for discovered but neighbors not fully processed
# black for discovered and neighbors fully processed
u.color <- white
u.d <- ∞ # d for distance
u.p <- nil # p for parent node
# Below function can be wrapped up as "BFS-Visit(G,s)"
s. color <- gray
s.d <- 0
initialize an empty queue Q
Enqueue(Q,s) #Q.append(s) in Python
while Q ≠ ∅ do
u <- u = Dequeue(Q) # Q.pop() in Python
for each v ∈ Adj(u) # Adj for all the neighboring nodes of u
if v.color == white then
v.color <- grey
v.d <- u.d + 1
v.p <- u
Enqueue(Q,v)
u.color <- black # This part is for noting purpose from my perspective

DFS — поиск в глубину
Вместо того, чтобы исследовать граф «послойно», DFS будет начинать с одного узла и исследовать путь до конца, а затем делать шаги назад. Но каждый шаг назад, к предыдущему узлу, он будет исследовать, есть ли другие пути, которые он может расширить.
Вам станет намного понятнее, если вы увидите псевдокод ниже:
DFS(G):
for each vertex u ∈ V do
u.color <- white
u.p <- nil
for each vertex u ∈ V do
if u.color == white then
DFS_Visit(u) # Defined below
DFS_Visit(u):
u.color <- grey
for each v ∈ Adj(u) do
v.p <- u
DFS_Visit(v)
u.color <- black

Алгоритм топологической сортировки
Если у нас есть ориентированный ациклический граф (DAG), состоящий из k узлов. Топологическое упорядочение графа означает, что мы произвольно выбираем две вершины (u, v) в графе, и u должен стоять перед v.
Псевдокод:
Topological Sort (G):
Initialize Q to be an empty queue
Initialize O to be an empty queue #Store the topological order
for each u in V do
If in-degree(u) == 0 then
# Find all starting vertices
Enqueue(Q,v)
while Q is not empty do
u = Dequeue(Q)
Enqueue(O,u)
for each v in Adj(u) do
# remove u's outgoing edges
in-degree(v) = in-degree(v) - 1
if in-degree(v) = 0 then
Enqueue(Q,v)
Советы для меня и потенциальных будущих читателей:
- Попрактикуйтесь в написании кодов для DFS, BFS и топологической сортировки без посторонней помощи.
Головоломка в конце
В: [Лемма о рукопожатии] Представьте себе группу людей, которые произвольно пожали друг другу руки. Возможно ли, чтобы количество людей, которые пожали друг другу руки нечетное количество раз, также было бы нечетным?
A: Используйте противоречие. Количество рукопожатий для каждого человека равно deg(v). Если есть нечетное количество людей, пожимающих друг другу руки нечетное число, то суммирование степеней также даст нечетное число.
нечетное + нечетное + … + нечетное + четное + четное + …+ четное = нечетное, если существует нечетное количество коэффициентов