Алгоритмы на графах и деревьях
Прямой обход произвольного связного графа
Для простоты изложения будем считать, что граф задан матрицей смежности, которая хранится в квадратном массиве sm. Дополнительный линейный массив mark хранит информацию о последовательности посещения вершин:
procedure preorder_graph(v: byte); var i: byte; begin k:= k+1; mark[v]:= k; {текущей вершине v присвоен порядковый номер} for i:= 1 to n do if (mark[i]=0)and(sm[v,i]=1) {есть ребро из текущей вершины v в еще не помеченную вершину i} then preorder_graph(i); end; begin ... k:= 0; preorder_graph(start); {Вызов из тела программы} ... end.
Обратный обход
Другие названия
Постфиксный обход: результатом обратного обхода ДСА арифметического выражения будет постфиксный вариант записи этого выражения.
Обход в глубину "снизу вверх": название имеет смысл лишь в случае стандартного расположения дерева корнем кверху.
Алгоритм PostOrder
- Начать с корня дерева.
- Совершить обратный обход левого поддерева.
- Совершить обратный обход правого поддерева.
- Пометить текущую вершину.
Замечание: Этот алгоритм также может быть распространен на случай произвольного корневого дерева.
Реализация
procedure postorder(p:ukaz; k:integer); begin if p^.left<>nil then postorder(p^.left,k+1); if p^.right<>nil then postorder(p^.right,k+1) p^.mark:=k; end; begin ... postorder(root,1); {Вызов из тела программы} ... end.
Обратный обход произвольного связного графа
Для простоты изложения будем считать, что граф задан матрицей смежности, которая хранится в квадратном массиве sm. Дополнительный линейный массив mark хранит информацию о последовательности обхода вершин, а массив posesh - о фактах их посещения:
procedure postorder_graph(v:byte); var i: integer; begin posesh[v]:=1; {текущая вершина v стала посещенной} for i:=1 to n do if (posesh[i]=0)and(sm[v,i]=1) {есть ребро из текущей вершины v в еще не помеченную вершину i} then postorder_graph(i); inc(k); mark[v]:=k; {текущей вершине v присвоен порядковый номер} end; begin ... k:=0; postorder_graph(start); {вызов из тела программы} ... end.
Синтаксический обход
Другие названия
Инфиксный обход: результатом синтаксического обхода ДСА арифметического выражения будет инфиксный вариант записи этого выражения.
Обход "слева направо": название имеет смысл лишь в случае стандартного расположения дерева корнем кверху.
Алгоритм SyntOrder
- Начать с корня дерева.
- Совершить прямой обход левого поддерева.
- Пометить текущую вершину.
- Совершить прямой обход правого поддерева.
Замечание: Этот обход специфичен только для бинарных деревьев, поэтому невозможно применить его к произвольному графу, каркасом которого совершенно не обязательно будет именно бинарное дерево.
Реализация
procedure syntorder(p:ukaz; k:integer); begin if p^.left<>nil then syntorder(p^.left,k+1); p^.mark:=k; if p^.right<>nil then syntorder(p^.right,k+1); end; begin ... syntorder(root,1); {Вызов из тела программы} ... end.