- •Предназначено студентам очной формы обучения.
- •Введение
- •1. Оценки сложности алгоритмов
- •1.1. Определение понятия алгоритм
- •1.2. Оценка сложности алгоритмов
- •2. Линейные структуры данных
- •2.1. Методы организации и хранения линейных списков
- •2.2. Операции со списками при последовательном хранении
- •2.3. Операции со списками при связном хранении
- •2.4. Организация двусвязных списков
- •Задания для самоконтроля
- •2.5. Стеки и очереди
- •2.6. Сжатое и индексное хранение линейных списков
- •3. Сортировка и слияние
- •3.1. Пузырьковая сортировка
- •3.2. Сортировка вставкой
- •3.3. Сортировка посредством выбора
- •3.4. Сортировка квадратичной выборкой
- •3.5. Слияние списков
- •3.6. Сортировка списков путем слияния
- •3.7. Быстрая и распределяющая сортировки
- •4. Поиск
- •4.1. Последовательный поиск
- •4.2. Бинарный поиск
- •4.4. Методы вычисления адреса
- •4.5. Выбор в линейных списках
- •5. Рекурсия
- •6. Алгоритмы на графах и сетях
- •6.1. Исходные понятия
- •6.2. Матричные представления графов
- •6.3. Другие представления графов
- •6.4. Поиск в глубину как система исследования графа
- •6.5. Перебор цепей поиском в глубину
- •6.6. Взвешенные графы. Ориентированные графы
- •6.7. Нахождение фундаментального множества циклов
- •6.8. Выявление мостов и точек сочленений
- •6.9. Поиск в ширину как система исследования графа
- •6.10. Кратчайшие пути, ведущие от заданного узла X ко всем прочим
- •6.11. Алгоритм Дейкстры нахождения кратчайших путей во взвешенном графе
- •6.12. Улучшения алгоритма Дейкстры
- •6.13. Построение кратчайшего каркаса
- •6.14. Нахождение всевозможных кратчайших путей в графе
- •6.15. Потоковые задачи
- •6.16. Пример практической задачи на графах
- •7. Генераторы случайных и псевдослучайных последовательностей
- •7.1. Общая постановка задачи
- •7.3. Генератор случайных чисел, поставляемый с системой
- •7.4. Генератор с малым кодом
- •7.5. Генератор Парка-Миллера
- •7.6. Улучшенная версия генератора Парка-Миллера
- •7.7. Быстрый генератор для 32-битового представления целых и действительных чисел
- •7.8. Алгоритм л'Экюера, комбинирующий две последовательности
- •Оглавление
- •7. Генераторы случайных и псевдослучайных последовательностей 144
- •394026 Воронеж, Московский просп., 14
6.5. Перебор цепей поиском в глубину
Вариантом "б" исчерпывающего исследования графа является перебор всевозможных цепей, начинающихся в заданном узле X. Он применяется для поиска оптимальной в каком-то смысле цепи или цепи, удовлетворяющей перечню требований.
Хотя алгоритм изменяется минимально, сложность поиска, как правило, выше, чем в варианте "а", и значительно, ибо одни и те же узлы участвуют в разных цепях, поэтому посещение узла при движении "вперед" может быть многократным. С этим связано и изменение в алгоритме. Делая шаг "назад" от некоторого узла Z, мы заменяем признак R(Z)=1 признаком R(Z)=0 (узел Z вновь доступен).
Упомянутое в п. 5.4 действие j:=L приобретает принципиальное значение: оно обеспечивает уникальность цепей; после возврата к узлу - Y движение "вперед" произойдет не к тому узлу, который прежде следовал за Y, а к иному (если он найдется). Поэтому две цепи поиска всегда различаются хотя бы одним узлом.
Пример 6.4.
Применим вариант "б" поиска в глубину к графу G1 (см. п.5.4) для вывода всех начинающихся в узле 5 цепей, не являющихся частью других цепей. Переменная b, принимающая значение true на шаге "вперед", нужна для распознания такой цепи. Текущая цепь представлена содержанием стека, вывод которого и производится.
Constn=9; {Значение п не должно превышать 254}
Type matr=Array[1..n,1..n] of byte; vek=Array[1..n] of byte;
Const A: matr=( (0,1,0,1,0,0,0,1,0), (1,0,1,0,0,1,0,0,0),
(0,1,0,1,1,0,1,0,0), (1,0,1,0,0,0,1,0,0),
(0,0,1,0,0,0,0,1,1), (0,1,0,0,0,0,0,0,0),
(0,'0,1,1,0,0,0,0,0), (1,0,0,0,1,0,0,0,0),
(0,0,0,0,1,0,0,0,0));
Procedure Cepi (Var A:matr; X:byte);
Var R,St:vek; b,c:Boolean; j,k,L:byte;
Begin For j:=1 to n do R[j]:=0;
k:=1;St[k]:=X; R[X]:= 1;j:=0;
RepeatL:= St[k]; {Начало главного цикла поиска в глубину}
с:= false; {Далее идет цикл поиска смежного узла j; R[j]=0}
Repeat j :=j+1;
If j > n Then c:= true
Else If (A[L,j]=1) And (R[j]=0) Then c:=true
Until с; {Или смежный узел найден,или L-я строка исчерпана}
Ifj>nThen {Шаг назад, ибо L-я строка исчерпана: }
Begin
IfbThen {Если предыдущий шаг был "вперед",выводим цепь}
Begin For j:=1 to k do Write(St[j],', '); Writeln; b:=false
End;
R[L]:=0;j:=L;k:=k-1 {Выделено специфическое действие}
End
Else {Шаг вперед, ибо подходящий смежный узел найден:}
Begin b:=true; k:=k+1; St[k]:= j; R[j]:= 1; j:= 0 End
Until k = 0
End;
BEGIN Cepi(A, 5); Readln;
END.
Даже в таком "нехитром" графе, как G1, выявляется 15 цепей, начинающихся в узле 5. При решении таких задач не пытайтесь создать "свою" систему, аккуратно встройте дополнительные действия в готовую. Например, для поиска цепи от X до Y, удовлетворяющей неким требованиям, надо включить сравнение очередного узла цепи с Y и проверку требовании. Если цепь не подходит, нужно искать следующую. Как это сделать?
Двигаться от Y "вперед" ни к чему. Отступить от Y на шаг?
Это годится. Достаточно передать системе управление таким образом, и автоматически будут выявлены и проверены другие цепи XY.
Итак, изменения обычно локализуются в главном цикле поиска в глубину. Если добавляемые действия - сложные, записывайте их в виде блоков, вызываемых из главного цикла.
Задание 6.5.
Составьте блок нахождения любой цепи XY для заданных X, Y, не проходящей через заданное множество узлов.