Алгоритмы на графах и деревьях
Построение из постфиксной записи
Для простоты предположим, что правильное арифметическое выражение подается в одной строке, без пробелов, а каждый операнд записан одной буквой. Кроме того, снова будем считать, что из записи удалены все скобки.
Алгоритм Postfix
- Если не достигнут конец строки ввода, прочитать очередной символ,если этот символ - операнд, то занести его в стек2См. лекцию 9.,иначе (символ - операция):
- создать новый элемент, записать в него эту операцию;
- достать из стека два верхних (последних) элемента, присоединить их в качестве левого и правого операндов в новый элемент;
- занести полученный "треугольник" в стек.
По окончании работы этого алгоритма в стеке будет содержаться ровно один элемент - указатель на корень построенного дерева.
Реализация
Для того чтобы упростить работу, добавим в структуру элемента дерева (см. рис. 1.12) дополнительное поле next:ukaz, которое будет служить для связки стека:
stek:= nil; while not eof(f) do begin new(p); read(f,p^.symbol); if p^.symbol in ['+','-','*','/'] then begin p^.right:= stek; p^.left:= stek^.next; p^.next:= stek^.next^.next; stek:= p end else begin p^.left:= nil; p^.right:= nil; p^.next:= stek; stek:= p end; end;
Обходы деревьев и графов
Прежде чем приступить к изложению алгоритмов обхода, дадим пару необходимых определений.
Обход дерева - это некоторая последовательность посещения всех его вершин.
Обход графа - это обход некоторого его каркаса.
В этом разделе будут представлены только алгоритмы обхода бинарных деревьев. Большинство из них может быть с легкостью изменено для случая произвольного корневого дерева, каковым является и каркас произвольного графа.
Напомним, что структуру бинарного дерева мы описываем следующим образом:
type ukazatel = ^tree; tree = record mark: integer; left: ukazatel; right: ukazatel; end;
Итак, приступим теперь к изучению различных вариантов обхода деревьев и графов.
Прямой обход
Другие названия
Префиксный обход: результатом прямого обхода3Точнее, результатом печати значений, содержащихся в вершинах ДСА. дерева синтаксического анализа арифметического выражения будет префиксный вариант записи этого выражения.
Обход в глубину "сверху вниз": название имеет смысл лишь в случае стандартного расположения дерева корнем кверху.
Алгоритм PreOrder
- Начать с корня дерева.
- Пометить4Вместо простой пометки вершины здесь можно производить выполнение любой осмысленной функции. текущую вершину.
- Совершить прямой обход левого поддерева.
- Совершить прямой обход правого поддерева.
Замечание: Этот алгоритм может быть естественным образом распространен и на случай произвольного корневого дерева.
Реализация
procedure preorder(p:ukaz; k:integer); begin p^.mark:= k; if p^.left<>nil then preorder(p^.left,k+1); if p^.right<>nil then preorder(p^.right,k+1); end; begin ... preorder(root,1); {Вызов из тела программы} ... end.