Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.
Алгоритмы на графах и
деревьях

1. Обходы в ширину и в
глубину
При работе с графами часто приходится
выполнять некоторое действие по одному разу
с каждой из вершин графа. Например,
неко...
Поиск в ширину
Пусть задан граф G = (V, Е) и выделена исходная
вершина s. Алгоритм поиска в ширину
систематически обходит ...
Поиск в ширину имеет такое название потому, что в
процессе обхода мы идем вширь, т.е. перед тем как
приступить к поиску ве...
Поиск в ширину строит дерево поиска в ширину,
которое изначально состоит из одного корня,
которым является исходная вершин...
Процедура поиска в ширину BFS
предполагает, что входной граф G = (V, Е)
представлен при помощи списков
смежности. Кроме то...
BFS(G, s)
1. for (для) каждой вершины u ∈ V[G] – s
2. do color[u] ← WHITE (значение белого цвета)
3.
d[u] ← ∞
4.
π[u] ← NI...
Процедура BFS работает следующим образом. В
строках 1 – 4 все вершины, за исключением
исходной вершины s, окрашиваются в б...
Инвариант данного цикла выглядит следующим образом:
При выполнении проверки в строке 10 очередь Q состоит
множества серых ...
Выполним анализ времени работы алгоритма для
входного графа
G = (V,E).
Сумма длин всех списков смежности равна O(|Е|),
общ...
Очередь имеет голову (head) и хвост (tail).
Очередь Q пуста, если выполняется
условие head[Q] = tail[Q].
Изначально выполн...
Enqueue(Q, x)
1. Q[tail[Q]] ← x
2. if tail[Q] = length[Q]
3. then tail[Q] ← 1
4. else tail[Q] ← tail[Q] + 1
Dequeue(Q)
1. ...
Поиск в глубину
Стратегия поиска в глубину, как следует из ее
названия, состоит в том, чтобы идти «вглубь»
графа, наскольк...
Подграф предшествования поиска в глубину
определяем как граф Gπ = (V, Еπ), где Еπ = {( π[v],
v) : v ∈ V и π[v] ≠ NIL} . По...
Помимо построения леса поиск в глубину также
проставляет в вершинах метки времени. Каждая
вершина имеет две такие метки – ...
Псевдокод алгоритма поиска в глубину. Входной
граф G может быть как ориентированным, так и
неориентированным. Переменная t...
DFS_Visit(u)
1. соlоr[u] ← GRAY //Открыта белая вершина u
2. time ← time + 1
3. d[u] ← time
4. for (для) каждой вершины v ...
В строках 5 – 7 поочередно проверяются все вершины из V,
и когда обнаруживается белая вершина, она
обрабатывается при помо...
Определим время работы процедуры DFS.
Циклы в строках 1 – 3 и
5–7
процедуры DFS выполняются за время Θ(|
V|), исключая вре...
общая стоимость выполнения строк 4 – 7
процедуры DFS_Visit равна Θ(|Е|). Время работы
процедуры DFS, таким образом, равно ...
Стек, способный вместить не более n элементов,
можно реализовать с помощью массива S[1..n].
Этот массив обладает атрибутом...
Próxima SlideShare
Cargando en…5
×

0

Compartir

Descargar para leer sin conexión

лекция 13

Descargar para leer sin conexión

Audiolibros relacionados

Gratis con una prueba de 30 días de Scribd

Ver todo
  • Sé el primero en recomendar esto

лекция 13

  1. 1. Алгоритмы на графах и деревьях 1. Обходы в ширину и в глубину
  2. 2. При работе с графами часто приходится выполнять некоторое действие по одному разу с каждой из вершин графа. Например, некоторую порцию информации следует передать каждому из компьютеров в сети. При этом мы не хотим посещать какой-либо компьютер дважды. Аналогичная ситуация возникает, если мы хотим собрать информацию, а не распространить ее. Подобный обход можно совершать двумя различными способами. При обходе в глубину проход по выбранному пути осуществляется настолько глубоко, насколько это возможно, а при обходе в ширину (по уровням) мы равномерно двигаемся вдоль всех возможных направлений.
  3. 3. Поиск в ширину Пусть задан граф G = (V, Е) и выделена исходная вершина s. Алгоритм поиска в ширину систематически обходит все ребра G для «открытия» всех вершин, достижимых из s, вычисляя при этом расстояние (минимальное количество ребер) от s до каждой достижимой из s вершины. Кроме того, в процессе обхода строится «дерево поиска в ширину» с корнем s, содержащее все достижимые вершины. Для каждой достижимой из s вершины v путь в дереве поиска в ширину соответствует кратчайшему (т.е. содержащему наименьшее количество s ребер) пути от s до v в G. Алгоритм работает как для ориентированных, так и для неориентированных графов.
  4. 4. Поиск в ширину имеет такое название потому, что в процессе обхода мы идем вширь, т.е. перед тем как приступить к поиску вершин на расстоянии k +1, выполняется обход всех вершин на расстоянии k. Для отслеживания работы алгоритма поиск в ширину раскрашивает вершины графа в белый, серый и черный цвета. Изначально все вершины белые, и позже они могут стать серыми, а затем черными. Когда вершина открывается в процессе поиска, она окрашивается. Таким образом, серые и черные вершины – это вершины, которые уже были открыты, но алгоритм поиска в ширину поразному работает с ними, чтобы обеспечить объявленный порядок обхода. Если (u, v) ∈ Е и вершина u черного цвета, то вершина v либо серая, либо черная, т.е. все вершины, смежные с черной, уже открыты. Серые вершины могут иметь белых соседей, представляя собой границу между открытыми и неоткрытыми вершинами.
  5. 5. Поиск в ширину строит дерево поиска в ширину, которое изначально состоит из одного корня, которым является исходная вершина s. Если в процессе сканирования списка смежности уже открытой вершины u открывается белая вершина v, то вершина v и ребро (u, v) добавляются в дерево. Мы говорим, что u является предшественником, или родителем, v в дереве поиска вширь. Поскольку вершина может быть открыта не более одного раза, она имеет не более одного родителя. Взаимоотношения предков и потомков определяются в дереве поиска в ширину как обычно – если и находится на пути от корня s к вершине u, то u является предком v, а u –потомком u.
  6. 6. Процедура поиска в ширину BFS предполагает, что входной граф G = (V, Е) представлен при помощи списков смежности. Кроме того, поддерживаются дополнительные структуры данных в каждой вершине графа. Цвет каждой вершины u ∈ V хранится в переменной color[u], а предшественник – в переменной π[u]. Если предшественника у u нет (например, если u = s или u не открыта), то π[u] = NIL. Расстояние от s до вершины u, вычисляемое алгоритмом, хранится в поле d[u]. Алгоритм использует очередь Q для работы с множеством серых вершин:
  7. 7. BFS(G, s) 1. for (для) каждой вершины u ∈ V[G] – s 2. do color[u] ← WHITE (значение белого цвета) 3. d[u] ← ∞ 4. π[u] ← NIL 5. color[s] ← GRAY (значение серого цвета) 6. d[s] ← 0 7. π[s] ← NIL 8. Q ← ∅ 9. Enqueue(Q, s) 10. while Q ≠ ∅ 11. do u ← Dequeue(Q) 12. for (для) каждой v ∈ Adj[u] 13. do if color[v] = WHITE 14. then color[v] ← GRAY 15. d[v] ← d[v] + 1 16. π[v] ← u 17. Enqueue(Q, v) 18. color[v] ← BLACK (значение черного цвета)
  8. 8. Процедура BFS работает следующим образом. В строках 1 – 4 все вершины, за исключением исходной вершины s, окрашиваются в белый цвет, для каждой вершины u полю d[u] присваивается значение ∞, а в качестве родителя для каждой вершины устанавливается NIL (пустое значение). В строке 5 исходная вершина s окрашивается в серый цвет, поскольку она рассматривается как открытая в начале процедуры. В строке 6 ее полю d[s] присваивается значение 0, а в строке 7 ее родителем становится NIL. В строках 8 – 9 создается пустая очередь Q, в которую помещается один элемент s. Цикл while в строках 10 – 18 выполняется до тех пор, пока остаются серые вершины (т.е. открытые, но списки смежности которых еще не просмотрены).
  9. 9. Инвариант данного цикла выглядит следующим образом: При выполнении проверки в строке 10 очередь Q состоит множества серых вершин. Перед первой итерацией единственной серой вершиной и единственной вершиной в очереди Q, является исходная вершина s. В строке 11 определяется серая вершина u в голове очереди Q, которая затем удаляется из очереди. Цикл for в строках 12 – 17 просматривает все вершины v в списке смежности u. Если вершина v белая, значит, она еще не открыта, и алгоритм открывает ее, выполняя строки 14 – 17. Вершине назначается серый цвет, дистанция d[v] устанавливается равной d[u] + 1, а в качестве ее родителя указывается вершина u. После этого вершина помещается в хвост очереди Q. После того как все вершины из списка смежности u просмотрены, вершине u присваивается черный цвет. Инвариант цикла сохраняется, так как все вершины, которые окрашиваются в серый цвет (строка 14), вносятся в очередь (строка 17), а вершина, которая удаляется из очереди (строка 11), окрашивается в черный цвет (строка 18).
  10. 10. Выполним анализ времени работы алгоритма для входного графа G = (V,E). Сумма длин всех списков смежности равна O(|Е|), общее время, необходимое для сканирования списков, равно O(|Е|). Накладные расходы на инициализацию равны O(|V|), так что общее время работы процедуры BFS составляет O(|V| + |Е|). Таким образом, время поиска в ширину линейно зависит от размера представления графа G с использованием списков смежности. Очередь – это динамическое множество, элементы из которого удаляются согласно стратегии «первым вошел – первым вышел» (first-in, firstout – FIFO).
  11. 11. Очередь имеет голову (head) и хвост (tail). Очередь Q пуста, если выполняется условие head[Q] = tail[Q]. Изначально выполняется соотношение head[Q] = tail[Q] = 1. Если head[Q] = tail[Q] + l, то очередь заполнена, и попытка добавить в нее элемент приводит к ее переполнению. Рассмотрим процедуры добавления элемента в очередь Enqueue и удаления элемента из очереди Dequeue (в них проверка ошибок опустошения и переполнения не производится).
  12. 12. Enqueue(Q, x) 1. Q[tail[Q]] ← x 2. if tail[Q] = length[Q] 3. then tail[Q] ← 1 4. else tail[Q] ← tail[Q] + 1 Dequeue(Q) 1. x ← Q[head[Q]] 2. if head[Q] = length[Q] 3. then head[Q] ← 1 4. else head[Q] ← head[Q] + 1 5. return x
  13. 13. Поиск в глубину Стратегия поиска в глубину, как следует из ее названия, состоит в том, чтобы идти «вглубь» графа, насколько это возможно. Когда вершина v открывается в процессе сканирования списка смежности уже открытой вершины u, процедура поиска записывает это событие, устанавливая поле предшественника v π[v] равным u. В отличие от поиска в ширину, где подграф предшествования образует дерево, при поиске в глубину подграф предшествования может состоять из нескольких деревьев, так как поиск может выполняться из нескольких исходных вершин.
  14. 14. Подграф предшествования поиска в глубину определяем как граф Gπ = (V, Еπ), где Еπ = {( π[v], v) : v ∈ V и π[v] ≠ NIL} . Подграф предшествования поиска в глубину образует лес поиска в глубину, который состоит из нескольких деревьев поиска в глубину. Ребра в Еπ называются ребрами дерева. Каждая вершина изначально белая, затем при открытии в процессе поиска она окрашивается в серый цвет, и по завершении, когда ее список смежности полностью сканирован, она становится черной. Такая методика гарантирует, что каждая вершина в конечном счете находится только в одном дереве поиска в глубину, так что деревья не пересекаются.
  15. 15. Помимо построения леса поиск в глубину также проставляет в вершинах метки времени. Каждая вершина имеет две такие метки – первую d[v], в которой указывается, когда вершина v открывается (и окрашивается в серый цвет), и вторая – f[v], которая фиксирует момент, когда поиск завершает сканирование списка смежности вершины v и она становится черной. Процедура DFS записывает в поле d[u] момент, когда вершина u открывается, а в поле f[u] – момент завершения работы с вершиной u. Эти метки времени представляют собой целые числа в диапазоне от 1 до 2|V|, поскольку для каждой из |V| вершин имеется только одно событие открытия и одно – завершения. Для каждой вершины u d[u] < f[u]. До момента времени d[u] вершина имеет цвет WHITE, между d[u] и f[u] – цвет GRAY, а после f[u] – цвет BLACK.
  16. 16. Псевдокод алгоритма поиска в глубину. Входной граф G может быть как ориентированным, так и неориентированным. Переменная time – глобальная и используется нами для меток времени. DFS(G) 1. for (для) каждой вершины u ∈ V[G) 2. do color[u] ← WHITE 3. π[u] ← NIL 4. time ← 0 5. for (для) каждой вершины u ∈ V[G) 6. do if color[u] = WHITE 7. then DFS_Visit(u)
  17. 17. DFS_Visit(u) 1. соlоr[u] ← GRAY //Открыта белая вершина u 2. time ← time + 1 3. d[u] ← time 4. for (для) каждой вершины v ∈ Adj[u] //Исследование ребра (u, v) 5. do if color[v] = WHITE 6. then π[v] ← u 7. DFS_Visit(v) 8. color[u] ← BLACK //Завершение 9. f[u] ← time ← time + 1 Процедура DFS работает следующим образом. В строках 1 – 3 все вершины окрашиваются в белый цвет, а их поля π инициализируются значением NIL. В строке 4 выполняется сброс глобального счетчика времени.
  18. 18. В строках 5 – 7 поочередно проверяются все вершины из V, и когда обнаруживается белая вершина, она обрабатывается при помощи процедуры DFS_Visit. Каждый раз при вызове процедуры DFS_Visit(u) в строке 7, вершина u становится корнем нового дерева леса поиска в глубину. При возврате из процедуры DFS каждой вершине u сопоставляются два момента времени – время открытия d[u] и время завершения f[u]. При каждом вызове DFS_Visit(u) вершина u изначально имеет белый цвет. В строке 1 она окрашивается в серый цвет, в строке 2 увеличивается глобальная переменная time, а в строке 3 выполняется запись нового значения переменной time в поле времени открытия d[u]. В строках 4 – 7 исследуются все вершины, смежные с u, и выполняется рекурсивное посещение белых вершин. При рассмотрении в строке 4 вершины v ∈ Adj[u], мы говорим, что ребро (u, v) исследуется поиском в глубину. И, наконец, после того как будут исследованы все ребра, покидающие u, в строках 8 – 9 вершина u окрашивается в черный цвет, а в поле f[u] записывается время завершения работы с ней.
  19. 19. Определим время работы процедуры DFS. Циклы в строках 1 – 3 и 5–7 процедуры DFS выполняются за время Θ(| V|), исключая время, необходимое для вызова процедуры DFS_Visit. Процедура DFS_Visit вызывается ровно по одному разу для каждой вершины v ∈ V, так как она вызывается только для белых вершин, и первое, что она делает, – это окрашивает переданную в качестве параметра вершину в серый цвет. В процессе выполнения DFS_Visit(v) цикл в строках 4 – 7 выполняется |Adj[v]| раз. Поскольку ∑| Adj[v] | = Θ(| E |) v∈V
  20. 20. общая стоимость выполнения строк 4 – 7 процедуры DFS_Visit равна Θ(|Е|). Время работы процедуры DFS, таким образом, равно Θ(|V| + | Е|). Процедура DFS_Visit является рекурсивной. Стек – это динамическое множество, элементы которого обрабатываются согласно стратегии «последним вошел – первым вышел» (last-in, first-out – LIFO). Чаще всего стек реализуется с помощью массива. Над стеком определены две основные операции – вставки и удаления элемента. Операция вставки применительно к стекам часто называется Push (запись в стек), а операция удаления – Pop (снятие со стека).
  21. 21. Стек, способный вместить не более n элементов, можно реализовать с помощью массива S[1..n]. Этот массив обладает атрибутом top[S], представляющим собой индекс последнего помещенного в стек элемента. Стек состоит из элементов S [1.. top[S]], где S[1] – элемент на дне стека, а S[top[S]] – элемент на его вершине. Если top[S] = 0, то стек не содержит ни одного элемента и является пустым. Протестировать стек на наличие в нем элементов можно с помощью операции-запроса Stack_Empty. Stack_Empty(E) 1. if top[S] = 0 2. then return TRUE

Vistas

Total de vistas

227

En Slideshare

0

De embebidos

0

Número de embebidos

9

Acciones

Descargas

2

Compartidos

0

Comentarios

0

Me gusta

0

×