Справочник от Автор24
Поделись лекцией за скидку на Автор24

Графы

  • 👀 530 просмотров
  • 📌 486 загрузок
Выбери формат для чтения
Загружаем конспект в формате pdf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Конспект лекции по дисциплине «Графы» pdf
Графы Лекция 10 Понятие графа ▪ Граф (graph) – это совокупность непустого множества 𝑉 вершин и множества 𝐸 ребер 𝐺 = 𝑉, 𝐸 , 𝑛 = 𝑉 , 𝑚 = |𝐸|, 𝑉 = 1,2, … , 𝑛 , 𝐸 = { 𝑢1 , 𝑣1 , 𝑢2 , 𝑣2 , … , (𝑢𝑚 , 𝑣𝑚 )} vertex edge 𝑽 = 𝟏, 𝟐, 𝟑, 𝟒, 𝟓 𝑬 = 𝟏, 𝟓 , 𝟐, 𝟓 , 𝟐, 𝟑 , 𝟐, 𝟒 , (𝟑, 𝟒) (1, 5) и (5, 1) – это одно и тоже ребро 2 Виды графов Граф ы (graphs) Неориентированные граф ы (undirected graphs) Ориентированные граф ы (directed graphs) Ребра (edges) не имеют направлений Ребра – дуги (arcs, edges) имеют направления (1, 2) и (2, 1) – одно и тоже ребро (1, 3) и (3, 1) – разные дуги! 3 Основные определения Вершина (vertex, node) Ребро (edge, link) Смежные вершины (adjacent vertices) Ребро (4, 6) инцидентно (incident) вершинам 4 и 6 Путь (path) – последовательность вершин, в которой следующая вершина (после первой) является смежной с предыдущей (все вершины и ребра в пути различны) Путь: (10, 8, 3, 5) 4 Основные определения Цикл (cycle) – путь, в котором первая и последняя вершины совпадают: (4, 6, 7, 8, 3, 4) Степень вершины (vertex degree) – количество ребер, инцидентных вершине deg(7) = 2, deg(1) = 3 Связный граф (connected graph) – граф, в котором существует путь из каждой вершины в любую другую 5 Основные определения ▪ Взвешенный граф (weighted graph) – это граф, ребрам (дугам) которого назначены веса ▪ Вес ребра (𝑖, 𝑗) обозначим как 𝑤𝑖𝑗 𝑤34 = 5, 𝑤42 = 24, … 6 Основные определения Полный граф (complete graph) – это граф, в котором каждая пара различных вершин смежна (каждая вершина соединена со всеми) Количество ребер в полном неориентированном графе: 𝑛(𝑛 − 1) 𝑚= 2 Насыщенность D неориентированного граф а (density): 2𝑚 𝐷= 𝑛(𝑛 − 1) У полного графа насыщенность D = 1 2∙4 8 𝐷= = = 0.66 4 ∙ 3 12 7 Основные определения Насыщенный граф (dense graph) – это граф, в котором количество ребер близко к максимально возможному 𝐸 = 𝑂( 𝑉 2 ) 𝐷= 2∙19 7∙6 = 0.9, 𝐷 > 0.5 Разреженный граф (sparse graph) – граф, в котором количество ребер близко к количеству вершин в графе 𝐸 = 𝑂(|𝑉|) 𝐷= 2∙7 7∙6 = 0.33, 𝐷 < 0.5 8 Представление графов в памяти ▪ Представление графа в памяти (формат его хранения) определяет вычислительную сложность операций над графом и объем требуемой памяти ▪ Основные способы представления графов в памяти:  Матрица смежности (adjacency matrix) эффективна для насыщенных графов  Списки смежных вершин (adjacency lists) эффективны для разреженных графов 9 Матрица смежности ▪ Матрица A смежности (adjacency matrix) – это матрица n × n элементов, в которой 1, если 𝑖, 𝑗 ∈ 𝐸, 𝑎𝑖𝑗 = ቊ 0, иначе. ▪ Объем требуемой памяти 𝑂( 𝑉 2 ) ▪ Быстрое определение присутствия ребра (𝑖, 𝑗) в графе ▪ За время 𝑂(1) получаем доступ к элементу 𝑎𝑖𝑗 матрицы Эффективна для насыщенных графов (|𝐸| ≈ |𝑉|2) 10 Матрица смежности ▪ Какого размера граф можно разместить в оперативной памяти объемом 8 Гб, используя матрицу смежности? int a[n][n]; 11 Матрица смежности ▪ Какого размера граф можно разместить в оперативной памяти объемом 8 ГиБ, используя матрицу смежности? int a[n][n]; sizeof(int)= 4 байта 8 ГиБ = 8 ∙ 230 байт 8 ∙ 230 / 4 = 2 ∙ 230 – можно разместить 231 = 2 147 483 648 элементов типа int 𝑛= 231 = 46340 – количество строк и столбцов int a[46340][46340]; ▪ Надо учесть, что часть памяти занята ОС и другими программами (предполагаем, что доступно 90% памяти (~ 7 ГиБ), тогда n = 43347) ▪ ▪ ▪ ▪ 12 Списки смежных вершин ▪ Списки смежных вершин (adjacency lists) – это массив 𝐴[𝑛], каждый элемент 𝐴[𝑖] которого содержит список узлов, смежных с вершиной Эффективен для разреженных графов (|𝐸| ≈ |𝑉|) 13 Списки смежных вершин ▪ Реализация списка смежных вершин на основе массивов 𝐴[𝑛 + 1] и 𝐿[2𝑚] ▪ Список смежных вершин узла 𝑖: 𝐿[𝐴[𝑖]], 𝐿[𝐴[𝑖] + 1], … , 𝐿[𝐴[𝑖 + 1] – 1] 1 A: 1 2 3 4 3 7 10 12 13 15 – индексы начала и конца списка смежных вершин в массиве L 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 2 4 1 3 5 6 2 4 6 1 3 2 2 3 6 L: 5 6 7 14 Списки смежных вершин // Обход смежных вершин узла i for (j = A[i]; j < A[i + 1]; j++) { v = L[j]; // Обработать вершину v } 𝑻 = 𝑶(𝒎) ▪ Количество смежных узлов вершины 𝑖: 𝐴[𝑖 + 1] – 𝐴[𝑖] A: L: 1 2 3 4 5 6 7 1 3 7 10 12 13 15 – индексы начала и конца списка смежных вершин в массиве L 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 2 4 1 3 5 6 2 4 6 1 3 2 2 3 6 15 Графы в реальной жизни ▪ Задан начальный пользователь (узел графа) ▪ Как, начиная со стартового узла, найти пользователя с заданным именем? ▪ Как перебрать всех пользователей и применить к ним некоторую процедуру?  изменить профиль  вычислить число пользователей старше 20 лет Граф социальной сети 16 Графы в реальной жизни ▪ Обход граф а (graph traversal) – это процедура перебора (посещения) всех вершин графа, начиная с заданной 17 Поиск в глубину (depth-first search) ▪ Поиск в глубину (depth-first search – DFS) – процедура посещения всех вершин графа, начиная с заданного узла v ▪ Сперва посещаем (обрабатываем) все самые “глубокие” вершины function DFS(v) visited[v] = true // Обрабатываем данные вершины v for each u in Adj(v) do // Перебор смежных вершин if visited[u] = false then DFS(u) // Рекурсивно обрабатываем вершину u end if end for end function 18 Поиск в глубину (depth-first search) ▪ Обход в глубину с вершины 2: DFS(2) for each u in Adj(2) do ... end for ▪ Обход в глубину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в глубину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 19 Поиск в глубину (depth-first search) ▪ Обход в глубину с вершины 2: DFS(2) for each u in Adj(2) do ... end for ▪ Обход в глубину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в глубину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 20 Поиск в глубину (depth-first search) ▪ Обход в глубину с вершины 2: DFS(2) for each u in Adj(2) do ... end for ▪ Обход в глубину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в глубину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 21 Поиск в глубину (depth-first search) ▪ Обход в глубину с вершины 2: DFS(2) for each u in Adj(2) do ... end for ▪ Обход в глубину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в глубину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 22 Поиск в глубину (depth-first search) ▪ Обход в глубину с вершины 2: DFS(2) for each u in Adj(2) do ▪ Все смежные вершины узла 5 ... посещены end for ▪ Возвращаемся к узлу 3 ▪ Обход в глубину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в глубину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 23 Поиск в глубину (depth-first search) ▪ Обход в глубину с вершины 2: DFS(2) for each u in Adj(2) do ... end for ▪ Обход в глубину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в глубину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 24 Поиск в глубину (depth-first search) ▪ Обход в глубину с вершины 2: DFS(2) for each u in Adj(2) do ... end for ▪ Обход в глубину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в глубину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 25 Поиск в глубину (depth-first search) ▪ Обход в глубину с вершины 2: DFS(2) for each u in Adj(2) do ... ▪ Все смежные вершины узла 6 посещены end for ▪ Возвращаемся к узлу 7, затем к 8 ▪ Обход в глубину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в глубину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 26 Поиск в глубину (depth-first search) ▪ Обход в глубину с вершины 2: DFS(2) for each u in Adj(2) do ▪ Все смежные вершины узла 9 ... посещены end for ▪ Возвращаемся к узлу 8 ▪ Обход в глубину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в глубину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 27 Поиск в глубину (depth-first search) ▪ Обход в глубину с вершины 2: DFS(2) for each u in Adj(2) do ... end for ▪ Обход в глубину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в глубину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 28 Поиск в ширину (breadth-first search) ▪ Поиск в ширину (breadth-first search – BFS, обход в ширину) – процедура посещения всех вершин графа, начиная с заданного узла v ▪ Сперва посещаем (обрабатываем) свои дочерние вершины 29 Поиск в ширину (breadth-first search) function BFS(v) visited[v] = true // Обрабатываем вершину v QueueEnqueue(v) // Помещаем v в очередь вершин while QueueSize() > 0 do u = QueueDequeue() // Извлекаем вершину for each x in Adj(u) do if visited[x] = false then QueueEnqueue(x) visited[x] = true // Обрабатываем узел x end if end for end while end function 30 Поиск в ширину (breadth-first search) ▪ Обход в ширину с вершины 2: BFS(2) ▪ Извлекли из очереди: 2 ▪ В очереди: 1, 3, 5 ▪ Обход в ширину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в ширину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 31 Поиск в ширину (breadth-first search) ▪ Обход в ширину с вершины 2: BFS(2) ▪ Извлекли из очереди: 1 ▪ В очереди: 3, 5, 4 ▪ Обход в ширину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в ширину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 32 Поиск в ширину (breadth-first search) ▪ Обход в ширину с вершины 2: BFS(2) ▪ Извлекли из очереди: 3 ▪ В очереди: 5, 4, 8 ▪ Обход в ширину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в ширину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 33 Поиск в ширину (breadth-first search) ▪ Обход в ширину с вершины 2: BFS(2) ▪ Извлекли из очереди: 5 ▪ В очереди: 4, 8 ▪ Обход в ширину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в ширину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 34 Поиск в ширину (breadth-first search) ▪ Обход в ширину с вершины 2: BFS(2) ▪ Извлекли из очереди: 4 ▪ В очереди: 8, 6 ▪ Обход в ширину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в ширину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 35 Поиск в ширину (breadth-first search) ▪ Обход в ширину с вершины 2: BFS(2) ▪ Извлекли из очереди: 8 ▪ В очереди: 6, 7, 9, 10 ▪ Обход в ширину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в ширину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 36 Поиск в ширину (breadth-first search) ▪ Обход в ширину с вершины 2: BFS(2) ▪ Извлекли из очереди: 6 ▪ В очереди: 7, 9, 10 ▪ Обход в ширину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в ширину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 37 Поиск в ширину (breadth-first search) ▪ Обход в ширину с вершины 2: BFS(2) ▪ Извлекли из очереди: 7 ▪ В очереди: 9, 10 ▪ Обход в ширину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в ширину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 38 Поиск в ширину (breadth-first search) ▪ Обход в ширину с вершины 2: BFS(2) ▪ Извлекли из очереди: 9 ▪ В очереди: 10 ▪ Обход в ширину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в ширину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 39 Поиск в ширину (breadth-first search) ▪ Обход в ширину с вершины 2: BFS(2) ▪ Извлекли из очереди: 10 ▪ В очереди: ▪ Обход в ширину графа, представленного матрицей смежности, имеет трудоемкость 𝑂(|𝑉|2) ▪ Обход в ширину графа, представленного списком смежности, имеет трудоемкость 𝑂(|𝑉| + |𝐸|) 40 Реализация графа на базе матрицы смежности #include #include #include "queue_array.h" struct graph { int nvertices; int *m; int *visited; }; /* Число вершин */ /* Матрица n x n */ 41 Реализация графа на базе матрицы смежности struct graph *graph_create(int nvertices) { struct graph *g; TCreate = O(n2) g = malloc(sizeof(*g)); g->nvertices = nvertices; g->visited = malloc(sizeof(int) * nvertices); g->m = malloc(sizeof(int) * nvertices * nvertices); graph_clear(g); // Опционально, O(n^2) return g; Memory = O(n2) } 42 Реализация графа на базе матрицы смежности void graph_clear(struct graph *g) { int i, j; } for (i = 0; i < g->nvertices; i++) { g->visited[i] = 0; for (j = 0; j < g->nvertices; j++) { g->m[i * g->nvertices + j] = 0; } } TClear = O(n2) 43 Реализация графа на базе матрицы смежности void graph_free(struct graph *g) { free(g->m); free(g); } 44 Реализация графа на базе матрицы смежности /* * graph_set_edge: Назначает ребру (i, j) вес w * i, j = 1, 2, ..., n */ void graph_set_edge(struct graph *g, int i, int j, int w) { g->m[(i - 1) * g->nvertices + j - 1] = w; g->m[(j - 1) * g->nvertices + i - 1] = w; } int graph_get_edge(struct graph *g, int i, int j) { return g->m[(i - 1) * g->nvertices + j - 1]; } 45 Обход графа в глубину (DFS) – рекурсивная версия void graph_dfs(struct graph *g, int v) { int i; g->visited[v - 1] = 1; printf("Vertex %d\n", v); } for (i = 0; i < g->nvertices; i++) { if (g->m[(v - 1) * g->nvertices + i] > 0 && g->visited[i] == 0) { graph_dfs(g, i + 1); } } TDFS = O(n2) 46 Обход графа в ширину (BFS) void graph_bfs(struct graph *g, int v) { int i, j; struct queue *q; for (i = 0; i < g->nvertices; i++) g->visited[i] = 0; // Создаем очередь q = queue_create(g->nvertices); // Обрабатываем стартовую вершину g->visited[v - 1] = 1; printf("Vertex %d\n", v); queue_enqueue(q, v - 1); 47 Обход графа в ширину (BFS, продолжение) } while (queue_size(q) > 0) { i = queue_dequeue(q); for (j = 0; j < g->nvertices; j++) { if (g->m[i * g->nvertices + j] > 0 && g->visited[j] == 0) { queue_enqueue(q, j); g->visited[j] = 1; printf("Vertex %d\n", j + 1); } } } queue_free(q); TBFS = O(n2) 48 Пример int main() { struct graph *g; g = graph_create(10); graph_set_edge(g, 1, 2, 1); graph_set_edge(g, 1, 4, 1); /* ... */ printf("DFS:\n"); graph_dfs(g, 2); printf("BFS:\n"); graph_bfs(g, 2); } graph_free(g); return 0; 49 Литература ▪ Доказательство вычислительной сложности процедур BFS и DFS [Aho, C. 217], [CLRS, С. 630, С. 639] ▪ Формат хранения графов в сжатом виде  Compressed Sparse Row Graph (CSR) http://www.boost.org/doc/libs/1_45_0/libs/graph/doc/compressed_sparse_row.html  Sparse matrix http://en.wikipedia.org/wiki/Sparse_matrix 50 Поиск кратчайшего пути в графе 51 поиск кратчайшего пути в графе ▪ Имеется взвешенный граф G = (V, E) ▪ Каждому ребру (i, j)  E назначен вес wij ▪ Заданы начальная вершина s  V и конечная d  V ▪ Требуется найти кратчайший путь из вершины s в вершину d (shortest path problem) ▪ Длина пути (path length, path cost, path weight) – это сумма весов ребер, входящих в него s (source) d (destination) Длина пути в графе  Длина пути (5, 4, 6, 7) = w54 + w46 + w67 = 4 + 6 + 9 = 19 s (source) d (destination) 53 Длина пути в графе  Длина пути (5, 4, 6, 7) = w54 + w46 + w67 = 4 + 6 + 9 = 19  Длина пути (5, 3, 8, 7) = 3 + 2 + 16 = 21 s (source) d (destination) 54 Длина пути в графе  Длина пути (5, 4, 6, 7) = w54 + w46 + w67 = 4 + 6 + 9 = 19  Длина пути (5, 3, 8, 7) = 3 + 2 + 16 = 21  Длина пути (5, 3, 4, 6, 7) = 3 + 3 + 6 + 9 = 21 s (source) d (destination) 55 Длина пути в графе  Длина пути (5, 4, 6, 7) = w54 + w46 + w67 = 4 + 6 + 9 = 19  Длина пути (5, 3, 8, 7) = 3 + 2 + 16 = 21  Длина пути (5, 3, 4, 6, 7) = 3 + 3 + 6 + 9 = 21 ▪ Альтернативные пути  (5, 1, 4, 3, 8, 7)  (5, 2, 3, 8, 7)  … s (source) d (destination) 56 постановка задачи о кратчайшем пути ▪ Задача о кратчайшем пути между парой вершин (single-pair shortest path problem) Требуется найти кратчайший путь из заданной вершины s в заданную вершину d ▪ Задача о кратчайших путях из заданной вершины во все (single-source shortest path problem) Найти кратчайшие пути из заданной вершины s во все ▪ Задача о кратчайшем пути в заданный пункт назначения (single-destination shortest path problem) Требуется найти кратчайшие пути в заданную вершину v из всех вершин графа ▪ Задача о кратчайшем пути между всеми парами вершин (all-pairs shortest path problem) Требуется найти кратчайший путь из каждой вершины u в каждую вершину v 57 Алгоритмы поиска кратчайшего пути в графе 58 Алгоритм Дейкстры ▪ Алгоритм Дейкстры (Dijkstra’s algorithm, 1959) – алгоритм поиска кратчайшего пути в графе из заданной вершины во все остальные (single-source shortest path problem) ▪ Находит кратчайшее расстояние от одной из вершин графа до всех остальных ▪ Применим только для графов без ребер отрицательного веса и петель (wij ≥ 0) ▪ Эдсгер Дейкстра (Edsger Wybe Dijkstra) – нидерландский ученый (структурное программирование, язык Алгол, семафоры, распределенные вычисления) ▪ Лауреат премии Тьюринга (ACM A.M. Turing Award) 1. Дейкстра Э. Дисциплина программирования = A discipline of programming. — М.: Мир, 1978. — С. 275. 2. Дал У., Дейкстра Э., Хоор К. Структурное программирование = Structured Programming. — М.: Мир, 1975. — С. 247. 59 Алгоритм Дейкстры ▪ Пример: найти кратчайший путь из вершины 1 в вершину 5 1 ▪ Введем обозначения: 10  H – множество посещенных вершин 100 2  D[i] – текущее известное 30 кратчайшее расстояние 50 5 от вершины s до вершины i 10  prev[i] – номер вершины, 60 3 предшествующей i в пути 20 4 60 Алгоритм Дейкстры 1. Устанавливаем расстояние D[i] от начальной вершины s до всех остальных в ∞ 10 2 2. Полагаем D[s] = 0 50 3. Помещаем все вершины в очередь с приоритетом Q (min-heap): 3 приоритет вершины i это значение D[i] D[i] 1 2 3 ∞ ∞ 1 4 5 ∞ ∞ 100 30 5 10 60 20 4 61 Алгоритм Дейкстры 1 1 10 4. Запускаем цикл из n итераций (по числу вершин) 1. 2. 3. Извлекаем из очереди Q вершину v с 2 минимальным приоритетом – ближайшую к s вершину Отмечаем вершину v как посещенную 50 (помещаем v во множество H) Возможно пути из s через вершину v стали 3 короче, выполняем проверку: для каждой вершины u, смежной с вершиной v и не включенной в H, проверяем и корректируем расстояние D[u] if D[v] + w(v, u) < D[u] then // Путь из s до u через (v, u) короче D[u] = D[v] + w(v, u) PrioQueueDecrease(Q, u, D[u]) prev[u] = v end if 100 30 5 10 60 20 4 D[2] = 10 D[4] = 30 D[5] = 100 D[i] 10 ∞ 30 100 62 Алгоритм Дейкстры 11 10 4. Запускаем цикл из n итераций (по числу вершин) 1. 2. 3. Извлекаем из очереди Q вершину v с 2 минимальным приоритетом – ближайшую к s 2 вершину Отмечаем вершину v как посещенную 50 (помещаем v во множество H) Возможно пути из s через вершину v стали 3 короче, выполняем проверку: для каждой вершины u смежной с вершиной v и не включенной в H проверяем и корректируем расстояние D[u] if D[v] + w(v, u) < D[u] then // Путь из s до u через (v, u) короче D[u] = D[v] + w(v, u) PrioQueueDecrease(Q, u, D[u]) prev[u] = v end if 100 30 5 10 60 20 4 D[3] = 60 D[i] 10 60 30 100 63 Алгоритм Дейкстры 11 10 4. Запускаем цикл из n итераций (по числу вершин) 1. 2. 3. Извлекаем из очереди Q вершину v с 2 минимальным приоритетом – ближайшую к s 2 вершину Отмечаем вершину v как посещенную 50 (помещаем v во множество H) Возможно пути из s через вершину v стали 3 короче, выполняем проверку: для каждой вершины u смежной с вершиной v и не включенной в H проверяем и корректируем расстояние D[u] if D[v] + w(v, u) < D[u] then // Путь из s до u через (v, u) короче D[u] = D[v] + w(v, u) PrioQueueDecrease(Q, u, D[u]) prev[u] = v end if D[i] 10 100 30 5 10 60 20 44 D[3] = 50 D[5] = 90 50 30 90 64 Алгоритм Дейкстры 11 10 4. Запускаем цикл из n итераций (по числу вершин) 1. 2. 3. Извлекаем из очереди Q вершину v с 2 минимальным приоритетом – ближайшую к s 2 вершину Отмечаем вершину v как посещенную 50 (помещаем v во множество H) Возможно пути из s через вершину v стали короче, выполняем проверку: для каждой 33 вершины u смежной с вершиной v и не включенной в H проверяем и корректируем расстояние D[u] if D[v] + w(v, u) < D[u] then // Путь из s до u через (v, u) короче D[u] = D[v] + w(v, u) PrioQueueDecrease(Q, u, D[u]) prev[u] = v end if D[i] 10 100 30 5 10 60 20 4 4 D[5] = 60 50 30 60 65 Алгоритм Дейкстры 11 10 4. Запускаем цикл из n итераций (по числу вершин) 1. 2. 3. Извлекаем из очереди Q вершину v с 2 минимальным приоритетом – ближайшую к s 2 вершину Отмечаем вершину v как посещенную 50 (помещаем v во множество H) Возможно пути из s через вершину v стали 3 короче, выполняем проверку: для каждой 3 вершины u смежной с вершиной v и не включенной в H проверяем и корректируем расстояние D[u] if D[v] + w(v, u) < D[u] then // Путь из s до u через (v, u) короче D[u] = D[v] + w(v, u) PrioQueueDecrease(Q, u, D[u]) prev[u] = v end if D[i] 10 100 30 5 5 10 60 20 4 4 50 30 60 66 Алгоритм Дейкстры ▪ В массиве D[1:n] содержатся длины кратчайших путей из начальной вершины s = 1 o o o o o D[1] – длина пути из 1 в 1 D[2] – длина пути из 1 в 2 D[3] – длина пути из 1 в 3 D[4] – длина пути из 1 в 4 D[5] – длина пути из 1 в 5 11 10 22 50 100 30 5 5 10 3 3 60 20 4 4 D[i] 0 10 50 30 60 ▪ Как определить, какие вершины входят в кратчайший путь из s = 1 в d = 5? ▪ Как восстановить путь? 67 Алгоритм Дейкстры ▪ Восстановление кратчайшего пути 10 ▪ Массив prev[i] содержит номер вершины, предшествующей i в пути prev[i] 1 2 3 4 5 -1 1 4 1 3 2 50 ▪ Восстанавливаем путь с конца  Вершина 5  Вершина prev[5] = 3  Вершина prev[3] = 4  Вершина prev[4] = 1 Кратчайший путь (1, 4, 3, 5) 1 100 30 5 10 60 3 20 D[i] 10 50 4 30 60 68 Алгоритм Дейкстры function ShortestPath_Dijkstra(G, src, d, prev) // Input: G = (V, E), src, dst // Output: d[1:n], prev[1:n] // prev[i] - узел, предшествующий i в пути // Помещаем вершины в очередь с приоритетом for each i in V \ {src} do d[i] = Infinity prev[i] = -1 PriorityQueueInsert(Q, i, d[i]) end for d[src] = 0 prev[src] = -1 PriorityQueueInsert(Q, src, d[src]) 69 Алгоритм Дейкстры for i = 0 to n – 1 do // Извлекаем узел ближайший к начальному v = PriorityQueueRemoveMin(Q) // Отмечаем v как посещенный H = H + {v} // Цикл по смежным вершинам узла v for each u in Adj(v) \ H do // Путь через u короче текущего пути? if d[v] + w(v, u) < d[u] then d[u] = d[v] + w(v, u) PriorityQueueDecrease(Q, u, d[u]) prev[u] = v end if end for end for end function 70 восстановление кратчайшего пути function SearchShortestPath(G, src, dst) ShortestPath_Dijkstra(G, src, d, prev) // Восстановление пути из src в dst i = dst pathlen = 1 while i != src do pathlen = pathlen + 1 i = prev[i] end while j = 0 i = dst while i != s do path[pathlen – j] = i i = prev[i] j = j + 1 end while return path[], pathlen end function T = TDijikstra + O(|V|) 71 Вычислительная сложность алгоритма Дейкстры ▪ Вычислительная сложность алгоритма Дейкстры определяется следующими факторами: 1) выбором структуры данных для хранения графа (матрица смежности, списки смежных вершин) 2) способом поиска вершины с минимальным расстоянием D[i]:  Очередь с приоритетом: Binary heap – O(logn), Fibonacchi heap, …  Сбалансированное дерево поиска: Red-black tree – O(logn), AVL-tree, …  Линейный поиск – O(n) 72 алгоритм дейкстры function ShortestPath_Dijkstra(G, src, d, prev) // Input: G = (V, E), src, dst // Output: d[1:n], prev[1:n] // prev[i] - узел, предшествующий i в пути // Помещаем вершины в очередь с приоритетом for each i in V \ {src} do d[i] = Infinity prev[i] = -1 PriorityQueueInsert(Q, i, d[i]) end for d[src] = 0 prev[src] = -1 PriorityQueueInsert(Q, src, d[src]) BinaryHeap 𝑂(𝑛 log 𝑛) 𝑂(log 𝑛) 73 алгоритм дейкстры for i = 0 to n – 1 do // Извлекаем узел ближайший к начальному v = PriorityQueueRemoveMin(Q) // Отмечаем v как посещенный H = H + {v} BinaryHeap 𝑂(log 𝑛) // Цикл по смежным вершинам узла v for each u in Adj(v) \ H do // Путь через u короче текущего пути? if d[v] + w(v, u) < d[u] then 𝑂(log 𝑛) d[u] = d[v] + w(v, u) PriorityQueueDecrease(Q, u, d[u]) prev[u] = v end if ▪ В худшем случае функция PriorityQueueRemoveMin() вызывается n end for раз, суммарная сложность 𝑂(𝑛 log 𝑛) end for ▪ В худшем случае функция PriorityQueueDecrease() вызывается для end function каждого из m ребер графа, суммарная сложность 𝑂(𝑚 log 𝑛) 74 вычислительная сложность алгоритма дейкстры ▪ Вариант 1. D[i] – это массив или список (поиск за время O (n)) 𝑇𝐷𝑖𝑗𝑖𝑘𝑠𝑡𝑟𝑎 = 𝑂 𝑛2 + 𝑚 = 𝑂( 𝑉 2 + 𝐸 ) ▪ Вариант 2. D[i] хранятся в бинарной куче (Binary heap) 𝑇𝐷𝑖𝑗𝑖𝑘𝑠𝑡𝑟𝑎 = 𝑂 𝑛 log 𝑛 + 𝑚 log 𝑛 = 𝑂(𝑚 log 𝑛) ▪ Вариант 3. D[i] хранятся в Фибоначчиевой куче (Fibonacci heap) 𝑇𝐷𝑖𝑗𝑖𝑘𝑠𝑡𝑟𝑎 = 𝑂 𝑚 + 𝑛 log 𝑛 ▪ Вариант 4. … ▪ В ориентированных ациклических графах (Directed acyclic graph) кратчайший путь можно найти за время O (n) 75 разреженные и насыщенные графы Насыщенный граф Разреженный граф 𝑚 = 𝑂(𝑛2 ) 𝑚 = 𝑂(𝑛) Вариант 1 D[i] – это массив (поиск за время O(n)) 𝑇 = 𝑂 𝑛2 + 𝑚 = 𝑶(𝒏𝟐 ) 𝑇 = 𝑂 𝑛2 + 𝑚 = 𝑶(𝒏𝟐 ) Вариант 2 D[i] хранятся в бинарной куче 𝑇 = 𝑂 𝑛 log 𝑛 + 𝑚 log 𝑛 = 𝑶(𝒏𝟐 𝐥𝐨𝐠 𝒏) 𝑇 = 𝑂 𝑛 log 𝑛 + 𝑚 log 𝑛 = 𝑶 𝒏 𝐥𝐨𝐠 𝒏 Вариант 3 D[i] хранятся в Фибоначчиевой куче 𝑇 = 𝑂 𝑚 + 𝑛 log 𝑛 = 𝑶(𝒏𝟐 ) 𝑇 = 𝑂 𝑛 + 𝑛 log 𝑛 = 𝑶(𝒏 𝐥𝐨𝐠 𝒏) Вариант реализации алгоритма Дейкстры 76 Алгоритм Дейкстры + бинарная куча ▪ Необходимые операции над очередью с приоритетом  int heap_insert(struct heap *h, int key, int value)  int heap_removemin(struct heap *h)  void heap_decreasekey(struct heap *node, int key) 77 Алгоритм Дейкстры + бинарная куча ▪ void heap_decreasekey(struct heap *node, int key) ▪ Изменяем у узла node приоритет на priority ▪ Восстанавливаем свойства кучи – поднимаем элемент вверх по дереву (min-heap) Prio: 3 Value: 6 Prio: 8 Value: 1 swap Prio: 13 Prio: 45 Value: 2 Value: 3 Prio: 9 Value: 4 heap_decreasekey(node, 2) 78 литература  Описание алгоритма Дейкстры в [CLRS, С. 696] 79
«Графы» 👇
Готовые курсовые работы и рефераты
Купить от 250 ₽
Решение задач от ИИ за 2 минуты
Решить задачу
Найди решение своей задачи среди 1 000 000 ответов
Найти

Тебе могут подойти лекции

Смотреть все 462 лекции
Все самое важное и интересное в Telegram

Все сервисы Справочника в твоем телефоне! Просто напиши Боту, что ты ищешь и он быстро найдет нужную статью, лекцию или пособие для тебя!

Перейти в Telegram Bot