Опубликован: 06.09.2005 | Уровень: для всех | Доступ: свободно
Лекция 12:

Алгоритмы на графах и деревьях

Прямой обход произвольного связного графа

Для простоты изложения будем считать, что граф задан матрицей смежности, которая хранится в квадратном массиве 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
  1. Начать с корня дерева.
  2. Совершить обратный обход левого поддерева.
  3. Совершить обратный обход правого поддерева.
  4. Пометить текущую вершину.

Замечание: Этот алгоритм также может быть распространен на случай произвольного корневого дерева.

Последовательность нумерации вершин при обратном обходе дерева

Рис. 12.3. Последовательность нумерации вершин при обратном обходе дерева
Реализация
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
  1. Начать с корня дерева.
  2. Совершить прямой обход левого поддерева.
  3. Пометить текущую вершину.
  4. Совершить прямой обход правого поддерева.

Замечание: Этот обход специфичен только для бинарных деревьев, поэтому невозможно применить его к произвольному графу, каркасом которого совершенно не обязательно будет именно бинарное дерево.

Реализация
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.
Евгения Поздеева
Евгения Поздеева
Ольга Стебакова
Ольга Стебакова

Вот фрагмент лекции 5 (статья 4):

Проверка множества на пустоту может быть осуществлена довольно просто:

pusto:= true;   for i:= 1 to N do 

if set_arr[i] then begin pusto:= false; break end; {мне кажется здесь должно быть так:

if set_arr[i]<>0 then begin pusto:= false; break end;}

Хотелось бы знать это ошибка в теории или я просто не поняла лекцию?