|
|
(не показано 5 промежуточных версий 3 участников) |
Строка 1: |
Строка 1: |
− | Алгоритм Дейкстры (Dijkstra) предназначен для решения задачи [[Поиск кратчайших путей в графе]].
| + | #REDIRECT [[discopal:{{PAGENAME}}]] |
− | | + | |
− | Важным фактом, позволяющим исключить перебор, является то, что если у нас есть кратчайший путь от ''v'' до ''w'', проходящий через вершину ''y'', назовем его <math>(v \rightarrow w)^*</math>, то его первая часть от ''v'' до ''y'', <math>(v \rightarrow y)^*</math>, тоже будет кратчайшим путем. Действительно, если бы это было не так, т.е. существовал бы путь <math>(v \rightarrow y)^!</math> длины меньшей, чем <math>(v \rightarrow y)^*</math>, то можно было бы улучшить оптимальный путь <math>(v \rightarrow w)^*</math>, заменив в нем <math>(v \rightarrow y)^*</math> на <math>(v \rightarrow y)^!</math>.
| + | |
− | | + | |
− | В алгоритме Дейкстры, мы, итерационно поддерживаем два множества вершин:
| + | |
− | | + | |
− | ;Visited: множество вершин, до которых мы уже нашли кратчайший путь, ассоциированных со стоимостями кратчайших путей от стартовой вершины до них.
| + | |
− | ;ToVisit: множество вершин, которые достижимы одним ребром из множества вершин ''Visited'', ассоциированных с верхними оценками стоимости пути до них.
| + | |
− | | + | |
− | На каждой итерации, мы выбираем из достижимых вершин вершину ''v'', самую ближайшую к стартовой вершине ''s'', и переносим ее из множества ''ToVisit'' в множество ''Visited'', увеличиваем множество «кандидатов» ''ToVisit'' ее соседями, и пересчитываем верхнюю оценку удаленности вершин из ''ToVisit'' до вершины ''s''.
| + | |
− | | + | |
− | В иллюстрации выполнения алгоритма, мы показываем изменение на каждой итерации хэш-таблиц ''Visited'' и ''ToVisit'', а в конце изображен входной граф, где сплошными линиями нарисованы имеющиеся ребра с ассоциированными длинами, а пунктиром — найденные кратчайшие пути.
| + | |
− | | + | |
− | Важно, что алгоритм работоспособен только в случае положительных расстояний, в противном случае, можно попробовать использовать [[алгоритм Флойда-Уоршолла]].
| + | |
− | | + | |
− | Код алгоритма, представлен в виде функции на языке [[Python]].
| + | |
− | | + | |
− | <code-python>
| + | |
− | # Находит кратчайшие пути из одной вершины | + | |
− | # во все остальные.
| + | |
− | def dijkstra(G,s):
| + | |
− | print "StartVertice:",s
| + | |
− | # хэш-таблица вершин, до которых построены кратчайшие пути, (узел:стоимость)
| + | |
− | Visited={}
| + | |
− | # хэш-таблица вершин, до которых еще не построены кратчайшие пути, (узел:стоимость)
| + | |
− | ToVisit={s:0}
| + | |
− | Paths = {s:[s]} # хэш-таблица (узел:кратчайший путь)
| + | |
− | while ToVisit: # пока есть вершины, до которых не построен кратчайший путь
| + | |
− | print Visited, ToVisit, "-------->",
| + | |
− | v=argmin(ToVisit) # выбираем ближайшую
| + | |
− | Visited[v]=ToVisit[v]; del ToVisit[v]; # считаем, что до нее кратчайший путь найден
| + | |
− | for w in G.neighbors(v): # для всех соседей вершины $v$
| + | |
− | if (w not in Visited): # к которым еще не нашли кратчайший путь
| + | |
− | vwLength = Visited[v] + G.get_edge(v,w) # обновляем кратчайшие пути
| + | |
− | if (w not in ToVisit) or (vwLength < ToVisit[w]):
| + | |
− | ToVisit[w] = vwLength
| + | |
− | Paths[w] = Paths[v]+[w]
| + | |
− | print Visited, ToVisit
| + | |
− | print Visited, Paths
| + | |
− | return (Visited,Paths)
| + | |
− | </code-python>
| + | |
− | | + | |
− | StartVertice: 2
| + | |
− | {} {2: 0} --------> {2: 0} {1: 15, 3: 20, 4: 15}
| + | |
− | {2: 0} {1: 15, 3: 20, 4: 15} --------> {1: 15, 2: 0} {0: 75, 3: 20, 4: 15}
| + | |
− | {1: 15, 2: 0} {0: 75, 3: 20, 4: 15} --------> {1: 15, 2: 0, 4: 15} {0: 75, 3: 20}
| + | |
− | {1: 15, 2: 0, 4: 15} {0: 75, 3: 20} --------> {1: 15, 2: 0, 3: 20, 4: 15} {0: 70}
| + | |
− | {1: 15, 2: 0, 3: 20, 4: 15} {0: 70} --------> {0: 70, 1: 15, 2: 0, 3: 20, 4: 15} {}
| + | |
− | {0: 70, 1: 15, 2: 0, 3: 20, 4: 15} {0: [2, 3, 0], 1: [2, 1], 2: [2], 3: [2, 3], 4: [2, 4]}
| + | |
− | | + | |
− | <graph>
| + | |
− | graph G{ rankdir=TB;
| + | |
− | 0 [label="NY(0)"];
| + | |
− | 1 [label="Moscow(1)"];
| + | |
− | 2 [label="Minsk(2)"];
| + | |
− | 3 [label="Berlin(3)"];
| + | |
− | 4 [label="Kiev(4)"];
| + | |
− | 0 -- 1[fontcolor="blue",label="$60",style=solid];
| + | |
− | 0 -- 3[fontcolor="blue",label="$50",style=solid];
| + | |
− | 0 -- 4[fontcolor="blue",label="$80",style=solid];
| + | |
− | 1 -- 2[fontcolor="blue",label="$15",style=solid];
| + | |
− | 1 -- 3[fontcolor="blue",label="$50",style=solid];
| + | |
− | 1 -- 4[fontcolor="blue",label="$10",style=solid];
| + | |
− | 2 -- 3[fontcolor="blue",label="$20",style=solid];
| + | |
− | 2 -- 4[fontcolor="blue",label="$15",style=solid];
| + | |
− | 3 -- 4[fontcolor="blue",label="$30",style=solid];
| + | |
− | 2 -- 3 -- 0 [fontcolor="red",label="Minsk-NY",style=dashed];
| + | |
− | 2 -- 1 [fontcolor="red",label="Minsk-Moscow",style=dashed];
| + | |
− | 2 -- 3 [fontcolor="red",label="Minsk-Berlin",style=dashed];
| + | |
− | 2 -- 4 [fontcolor="red",label="Minsk-Kiev",style=dashed];
| + | |
− | }
| + | |
− | </graph>
| + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | [[Category:Алгоритмы]]
| + | |
− | | + | |
− | {{replicate-from-custiswiki-to-lib}}
| + | |