Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 23_Алгоритмы поиска с возвращением.doc
Скачиваний:
1
Добавлен:
24.08.2019
Размер:
89.6 Кб
Скачать

Обходы ордерева в глубину и в ширину

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

Рис. 20. Дерево

При префиксном обходе ордерева T, сначала нужно посетить его корень v, а затем, если v не является листом, то реализовать префиксный обход всех ее поддеревьев в порядке их упорядоченности. Например, для дерева, показанного на рис. 20, вершины будут проходиться в следующем порядке: A,B,C,D,E,F,G,H,I,J,K,L. Следующая рекурсивная процедура реализует префиксный обход ордерева:

procedure ПРЕФИКСНЫЙ-ОБХОД(T: ордерево);  begin      Посетить корень v ордерева T    if v не лист then          Пусть T1,…,Tk – поддеревья корня v        for i := 1 to k do ПРЕФИКСНЫЙ-ОБХОД(Tiend      end  end.

Если использовать стек S для хранения текущего пути по дереву, т.е. пути, который начинается в корне дерева и кончается в вершине, посещаемой в данный момент, то можно предложить следующий нерекурсивный алгоритм префиксного обхода ордерева:

Посетить корень дерева и поместить его в пустой стек  S ;  while стек  S  не является пустым do      Пусть p  – вершина, находящаяся на верху стека  S ;      if Сыновья вершины p еще не посещались      then Посетить старшего сына вершины p и поместить его в стек  S       else             Удалить вершину p из стека S;              if p имеет братьев then Посетить брата вершины p и поместить его в стек  S  end      end  end

Способ обхода ордерева в ширину предполагает посещение вершин ордерева по старшинству, уровень за уровнем, отправляясь от корня. Например, при обходе в ширину изображенного на рис. 20 дерева вершины проходятся сверху вниз и слева направо и посещаются в следующем порядке: A,B,C,G,H,D,E,F,I,L,J,K. Приведенный ниже алгоритм реализует обход дерева в ширину, используя очередь О.

Поместить корень в пустую очередь Owhile очередь O не пуста do          Пусть p  – первая вершина очереди O;          Посетить вершину p  и удалить ее из O;          Поместить всех сыновей вершины p  в очередь O, начиная со старшего сына  end   

Следует заметить, что обход дерева поиска в ширину позволяет обходить дерево поиска одновременно с его построением. Таким образом, можно решать задачу нахождения какого-нибудь одного решения в форме вектора 1, а2,…)  неизвестной длины (не зная r), если только известно, что существует конечное решение задачи.

Обходы графа в глубину и в ширину

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

Например, используя рекурсивную процедуру, линейный по временной сложности алгоритм обхода графа G в глубину можно записать следующим образом:

procedure ОБХОД-В-ГЛУБИНУ(р: вершина);  begin      Посетить вершину р    for all q from множества вершин, смежных с р do          if q еще не посещалась then ОБХОД-В-ГЛУБИНУ(qend      end  end;  begin      for all р from множества вершин G do          if р еще не посещалась then ОБХОД-В-ГЛУБИНУ(рend      end  end.

В результате работы алгоритма, пройденные ребра графа образуют вместе с посещенными вершинами одно или несколько деревьев (по одному дереву для каждой компоненты связности графа). Если приписать пройденным ребрам ориентацию в соответствии с тем направлением, в каком они проходятся при выполнении алгоритма, то мы получим совокупность ордеревьев, причем их корнями будут служить все те вершины, которые в процессе работы алгоритма помещались в пустой стек.

Например, для графа, изображенного на рис. 21,а, описанным способом будут получены два ордерева, приведенных на рис. 21,б. Порядок на всем множестве вершин графа, а также порядок вершин, смежных всякой его вершине, соответствует алфавитному порядку букв, помечающих вершины.

Нерекурсивный вариант алгоритма обхода графа G в глубину может иметь следующий вид:

procedure ОБХОД-В-ГЛУБИНУ-1(р : вершина);  begin      Посетить вершину р  и поместить ее в пустой стек S    while Стек S непуст do              Пусть р  – вершина, находящаяся на верхушке стека S            if у р есть непосещенные смежные вершины then                      Пусть q – непосещенная вершина, смежная вершине р;                      Пройти по ребру (р, q), посетить вершину q и поместить ее в стек S              else Удалить вершину р из стека             end      end  end;

Рис. 21. Граф и его обход в глубину

Обход в ширину связного графа предполагает рассмотрение всех его вершин в порядке возрастания расстояния от некоторой вершины, с которой начался данный обход графа. Например, в результате обхода графа G (рис. 21) в ширину возможен следующий порядок посещения вершин: C,A,B,D,H,K,L,E,F,G.

 Следующий алгоритм позволяет осуществить обход в ширину любого связного графа G:  

procedure ОБХОД-В-ШИРИНУ(р: вершина);  begin      Поместить вершину р в пустую очередь O    while очередь O не пуста do              Взять первую вершину р из очереди O            if р еще не посещалась then                      Посетить вершину р и поместить в очередь все вершины, смежные с р              end      end  end;