Разница между алгоритмами Прима и Дейкстры?

В чем точная разница между алгоритмами Дейкстры и Прима? Я знаю, что Prim выдаст MST, но дерево, созданное Дейкстрой, также будет MST. Тогда в чем точная разница?


person anuj pradhan    schedule 03.01.2013    source источник
comment
Это Дейкстра. ij - дифтонг (скользящая гласная) в голландском языке, и это единственное место, где j не является согласным.   -  person    schedule 03.01.2013
comment
как бы то ни было, у вас есть вопрос.   -  person anuj pradhan    schedule 03.01.2013
comment
Лучший способ отличить их различие - прочитать исходный код, Дейкстра и Prim. Главное отличие здесь: для Prim graph[u][v] < key[v] и для Dijkstra dist[u]+graph[u][v] < dist[v]. Итак, как вы можете видеть из графиков на этих двух страницах, они отличаются в основном из-за этих двух строк кода.   -  person JW.ZG    schedule 18.02.2017


Ответы (15)


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

Алгоритм Дейкстры строит дерево кратчайших путей, начиная с некоторого исходного узла. Дерево кратчайшего пути - это дерево, которое соединяет все узлы в графе обратно с исходным узлом и обладает тем свойством, что длина любого пути от исходного узла до любого другого узла в графе минимизирована. Это полезно, например, если вы хотите построить дорожную сеть, которая сделает ее максимально эффективной для всех, чтобы добраться до какой-либо важной достопримечательности. Однако не гарантируется, что дерево кратчайшего пути будет минимальным остовным деревом, а сумма затрат на ребрах дерева кратчайшего пути может быть намного больше, чем стоимость MST.

Еще одно важное отличие состоит в том, на каких типах графиков работают алгоритмы. Алгоритм Прима работает только с неориентированными графами, поскольку концепция MST предполагает, что графы по своей природе неориентированы. (Для ориентированных графов существует так называемое «минимальное остовное древообразование», но алгоритмы их поиска намного сложнее). Алгоритм Дейкстры отлично работает на ориентированных графах, поскольку деревья кратчайших путей действительно могут быть направленными. Кроме того, алгоритм Дейкстры не обязательно дает правильное решение в графах, содержащих отрицательные веса ребер, в то время как алгоритм Прима может с этим справиться.

Надеюсь это поможет!

person templatetypedef    schedule 03.01.2013
comment
Первый абзац не имеет смысла, чувак. Вопрос в том, в чем разница между Dijkstra и Prim, где Dijkstra не о том, что вы сказали the length of a path between **any** two nodes, вы должны просто сосредоточить внимание на том, почему расстояние между узлом src и любыми другими узлами в Прим не самый короткий, если он не самый короткий. Я думаю, он, должно быть, спрашивает узел src в Prim о любом другом узле. Почему вы говорили о любых двух узлах в Prim? Это, конечно, не самое короткое. - person JW.ZG; 18.02.2017
comment
Я убрал формулировку в абзаце об алгоритме Дейкстры, чтобы уточнить, что дерево кратчайших путей является только минимизатором для кратчайших путей, берущих начало в исходном узле. Причина, по которой я структурировал свой ответ таким образом, заключалась в том, чтобы проиллюстрировать то, что находят алгоритмы, а не как они работают, чтобы показать на более высоком уровне, почему они дают разные результаты и почему вы не ожидал, что они будут такими же. - person templatetypedef; 18.02.2017
comment
Чтобы понять, почему диаграммы Дейкстры и Прима могут не возвращать одно и то же, рассмотрим радиальный граф с центральным узлом, соединенным, скажем, с 4 другими узлами, каждый с весом 3. Затем представьте, что между двумя из этих нецентральных узлов есть ребро. с весом 4. Кратчайший путь между этими двумя узлами - через прямое соединение, но это ребро не будет включено в MST. - person information_interchange; 16.10.2018
comment
Самое простое объяснение заключается в том, что в Prims вы не указываете начальный узел, но в dijsktra вам (необходимо иметь начальный узел) нужно найти кратчайший путь от данного узла. ко всем остальным узлам. См. stackoverflow.com/a/51605961/6668734 - person Deepak Yadav; 14.12.2019
comment
@DeepakYadav Некоторые определения Prim (например, CLRS ') предполагают, что вы действительно предоставляете начальную вершину. Вместо этого вы можете сказать, что Prim возвращает MST (и, таким образом, решает заявленную проблему) независимо от того, с какой вершины вы начинаете, тогда как у Дейкстры предоставление разных вершин решает разные (с одним источником) проблемы кратчайшего пути. - person Amelio Vazquez-Reina; 05.04.2020
comment
@templatetypedef - когда вы говорите: и стоимость построения такого дерева [с помощью Дейкстры] может быть намного больше, чем стоимость MST. не могли бы вы уточнить? - person Amelio Vazquez-Reina; 07.04.2020
comment
@ AmelioVazquez-Reina Простите, это двусмысленно. Я имел в виду, что сумма весов на ребрах дерева кратчайших путей может быть намного больше, чем сумма весов на ребрах в MST. - person templatetypedef; 07.04.2020
comment
+1 Спасибо. На самом деле я предположил, что вы имели в виду :). Я думаю, если вы замените это предложение именно тем, что написали, этот ответ будет еще яснее / лучше. - person Amelio Vazquez-Reina; 07.04.2020
comment
Ага, только что сделал это. - person templatetypedef; 07.04.2020

Алгоритм Дейкстры не создает MST, он находит кратчайший путь.

Рассмотрим этот график

       5     5
  s *-----*-----* t
     \         /
       -------
         9

Кратчайший путь - 9, в то время как MST - это другой «путь» на 10.

person dfb    schedule 03.01.2013
comment
Хорошо, спасибо ... вы очистили хороший момент, чтобы заметить. До сих пор я считал, что вывод, сгенерированный dijkstra, будет MST, но вы устранили сомнения с помощью хорошего примера. Я ясно вижу, найду ли я MST, используя, скажем, 'kruskal', тогда я получу тот же путь, что и вы упомянули . Большое спасибо - person anuj pradhan; 03.01.2013
comment
Вернее - The shortest path is 9 ... от з до т. Вес графа, сгенерированного алгоритмом Дейкстры, начиная с s, равен 14 (5 + 9). - person Bernhard Barker; 03.01.2013
comment
@ Дюкелинг - А? вес дерева / графа у Дейкстры бессмысленен, вот в чем дело .... - person dfb; 03.01.2013
comment
@dfb Вы доказывали, что это не MST, поэтому вес важен для этого. То же, что и 14 ›10, значит, это не MST. - person Bernhard Barker; 03.01.2013
comment
Очень лаконично проиллюстрировано! - person Ram Narasimhan; 03.06.2014
comment
@dfb: Обычно мы запускаем алгоритм Дейкстры только для получения кратчайшего пути между определенной парой вершин, но на самом деле вы можете продолжать, пока все вершины не будут посещены, и это даст вам дерево кратчайших путей, как объясняет ответ templatetypedef. - person j_random_hacker; 12.12.2014
comment
Я не понимаю этот график ты, может кто-нибудь подскажет, что это? - person Peter; 01.04.2020

Алгоритмы Прима и Дейкстры почти одинаковы, за исключением «функции релаксации».

Прим:

MST-PRIM (G, w, r) {
    for each key ∈ G.V
        u.key = ∞
        u.parent = NIL
    r.key = 0
    Q = G.V

    while (Q ≠ ø)
        u = Extract-Min(Q)
        for each v ∈ G.Adj[u]
            if (v ∈ Q)
                alt = w(u,v)    <== relax function, Pay attention here
                if alt < v.key
                    v.parent = u
                    v.key = alt
}

Дейкстра:

Dijkstra (G, w, r) {
    for each key ∈ G.V
        u.key = ∞
        u.parent = NIL
    r.key = 0
    Q = G.V

    while (Q ≠ ø)
        u = Extract-Min(Q)
        for each v ∈ G.Adj[u]
            if (v ∈ Q)
                alt = w(u,v) + u.key  <== relax function, Pay attention here
                if alt < v.key
                    v.parent = u
                    v.key = alt
}

Единственное различие указано стрелкой, которая является функцией релаксации.

  • Prim, который ищет минимальное остовное дерево, заботится только о минимуме из общего числа ребер, покрывающих все вершины. Функция релаксации alt = w(u,v)
  • Dijkstra, который ищет минимальную длину пути, поэтому он заботится о накоплении ребер. Функция релаксации alt = w(u,v) + u.key
person Albert Chen    schedule 12.09.2014
comment
На уровне кода другое отличие - это API. У Prim есть метод edges() для возврата ребер MST, а у Dijkstra есть distanceTo(v), pathTo(v), которые соответственно возвращают расстояние от источника до вершины v и путь от источника до вершины v, где s - это вершина, которой вы инициализируете Dijkstra. - person nethsix; 21.04.2016
comment
Следствие, инициализация Prim с любой любой исходной вершиной s возвращает тот же результат для edges(), но инициализация Dijkstra с другими s вернет другой результат для distanceTo(v), pathTo(v). - person nethsix; 21.04.2016
comment
Допускаются ли приматы отрицательный вес? если да, то это еще одна разница. Я читал, что вы можете разрешить отрицательные веса на примерах, добавив большое положительное число. к каждому значению, делая все это положительным. - person Akhil Dad; 23.11.2016
comment
Решила мою путаницу! Идеальный ответ !! - person Dhananjay Sarsonia; 06.11.2019
comment
здесь обрабатываемая вершина должна игнорироваться для неориентированного графа - person Mr AJ; 10.01.2020
comment
Невероятный ответ! Было интуитивно понятно, что эти два алгоритма очень похожи, но я не мог понять, как именно - спасибо за этот прекрасный ответ! - person fkotsian; 13.06.2021

Алгоритм Дийсктры находит минимальное расстояние от узла i до всех узлов (вы указываете i). Итак, взамен вы получаете дерево минимального расстояния от узла i.

Алгоритм Примса дает вам минимальное остовное дерево для данного графа. Дерево, которое соединяет все узлы, при этом сумма всех затрат минимально возможна.

Таким образом, с помощью Dijkstra вы можете перейти от выбранного узла к любому другому с минимальными затратами, вы не получите этого с помощью Prim's

person fersarr    schedule 10.12.2012
comment
Самое простое объяснение заключается в том, что в Prims вы не указываете начальный узел, но в dijsktra вам (необходимо иметь начальный узел) нужно найти кратчайший путь от данного узла. ко всем остальным узлам. См. stackoverflow.com/a/51605961/6668734 - person Deepak Yadav; 14.12.2019

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

Dijkstra дает вам путь от исходного узла к конечному узлу с минимальными затратами. Однако алгоритм Прима дает минимальное остовное дерево, в котором все узлы соединены, а общая стоимость минимальна.

Простыми словами:

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

person Kevindra    schedule 10.12.2012

Оба могут быть реализованы с использованием одного и того же универсального алгоритма следующим образом:

Inputs:
  G: Graph
  s: Starting vertex (any for Prim, source for Dijkstra)
  f: a function that takes vertices u and v, returns a number

Generic(G, s, f)
    Q = Enqueue all V with key = infinity, parent = null
    s.key = 0
    While Q is not empty
        u = dequeue Q
        For each v in adj(u)
            if v is in Q and v.key > f(u,v)
                v.key = f(u,v)
                v.parent = u

Для Прим пройти f = w(u, v), а для Дейкстры пройти f = u.key + w(u, v).

Еще одна интересная вещь заключается в том, что вышеупомянутый Generic также может реализовать поиск в ширину (BFS), хотя это было бы излишним, потому что дорогая очередь приоритетов на самом деле не требуется. Чтобы превратить общий алгоритм в BFS, передайте f = u.key + 1, что аналогично принудительному применению всех весов к 1 (то есть BFS дает минимальное количество ребер, необходимых для перехода от точки A к B).

Интуиция

Вот один хороший способ подумать о приведенном выше обобщенном алгоритме: мы начнем с двух сегментов A и B. Сначала поместите все ваши вершины в B, чтобы корзина A была пустой. Затем мы перемещаем одну вершину из B в A. Теперь посмотрим на все ребра из вершин в A, которые пересекаются с вершинами в B. Мы выбрали одно ребро, используя некоторые критерии из этих пересекающихся ребер, и переместили соответствующую вершину из B в A. Повторяйте этот процесс, пока B не станет пустым.

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

Исторический контекст

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

История начинается с Отакара Борувки, которому нужен был алгоритм для друга семьи, который пытался выяснить, как соединить города в Моравии (ныне часть Чешской Республики) с помощью линий электропередач с минимальными затратами. Он опубликовал свой алгоритм в 1926 году в журнале, посвященном математике, поскольку компьютерных наук тогда не существовало. Это привлекло внимание Войтеха Ярника, который подумал об улучшении алгоритма Борувки и опубликовал его в 1930 году. Он фактически открыл тот же алгоритм, который мы теперь знаем как алгоритм Прима, который повторно открыл его в 1957 году.

Независимо от всего этого, в 1956 году Дейкстре нужно было написать программу, чтобы продемонстрировать возможности нового компьютера, разработанного его институтом. Он подумал, что было бы здорово, если бы компьютер находил связи для путешествий между двумя городами Нидерландов. Он разработал алгоритм за 20 минут. Он создал график из 64 городов с некоторыми упрощениями (потому что его компьютер был 6-битным) и написал код для этого компьютера 1956 года. Однако он не опубликовал свой алгоритм, потому что в первую очередь не было журналов по информатике, и он думал, что это может быть не очень важно. В следующем году он узнал о проблеме подключения терминалов новых компьютеров таким образом, чтобы длина проводов была минимальной. Он подумал об этой проблеме и заново открыл алгоритм Ярника / Прима, который снова использует ту же технику, что и алгоритм кратчайшего пути, который он обнаружил годом ранее. Он упомянул, что оба его алгоритма были разработаны без использования пера или бумага. В 1959 году он опубликовал оба алгоритма в статье. это всего две с половиной страницы.

person Shital Shah    schedule 30.12.2014
comment
Спасибо! Выход нечеткий, почему он выходит из цикла, даже если ничего не происходит? - person amirouche; 01.09.2015

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

Алгоритм Prims дает вам MST для данного графа, то есть дерева, которое соединяет все узлы, в то время как сумма всех затрат является минимально возможной.

Короче говоря, на реалистичном примере:

  1. Дейкстра хочет узнать кратчайший путь к каждой точке назначения, сэкономив время в пути и топливо.
  2. Прим хочет знать, как эффективно развернуть железнодорожную систему, т.е. сэкономить на материальных затратах.
person Rahul    schedule 04.01.2013

Непосредственно из статьи в Википедии алгоритма Дейкстры:

Процесс, лежащий в основе алгоритма Дейкстры, похож на жадный процесс, используемый в алгоритме Прима. Цель Prim - найти минимальное остовное дерево, которое соединяет все узлы в графе; Дейкстра имеет дело только с двумя узлами. Prim не оценивает общий вес пути от начального узла, только отдельный путь.

person im so confused    schedule 03.01.2013
comment
Дейкстры занимаются только двумя узлами - отстой. - person tmyklebu; 31.08.2014

В последнее время меня беспокоил тот же вопрос, и я думаю, что могу разделить свое понимание ...

Я думаю, что ключевое различие между этими двумя алгоритмами (Dijkstra и Prim) коренится в проблеме, для решения которой они предназначены, а именно в кратчайшем пути между двумя узлами и минимальным остовным деревом (MST). Формально найти кратчайший путь, скажем, между узлами s и t, а рациональное требование - посетить каждое ребро графа не более одного раза. Однако это НЕ требует от нас посещения всех узлов. Последний (MST) должен заставить нас посетить ВСЕ узел (не более одного раза) и с тем же рациональным требованием посетить каждое ребро не более одного раза.

При этом Дейкстра позволяет нам «сокращаться» так долго, что я могу добраться от s до t, не беспокоясь о последствиях - как только я доберусь до t < / em>, готово! Хотя в MST также есть путь от s к t, но этот путь s - t создается с учетом всех остальных узлов, поэтому этот путь может быть длиннее, чем путь s - t, найденный алгоритмом Дийстры. Ниже приведен быстрый пример с 3 узлами:

                                  2       2  
                          (s) o ----- o ----- o (t)     
                              |               |
                              -----------------
                                      3

Допустим, каждое из верхних ребер имеет стоимость 2, а нижнее ребро имеет стоимость 3, тогда Дийктра скажет нам выбрать нижний путь, поскольку нас не волнует средний узел. С другой стороны, Prim вернет нам MST с двумя верхними краями, отбросив нижний край.

Такая разница также отражается в тонкой разнице в реализациях: в алгоритме Дейкстры необходимо иметь учетный шаг (для каждого узла), чтобы обновить кратчайший путь из s после поглощения нового узла , тогда как в алгоритме Прима в этом нет необходимости.

person ccy    schedule 19.10.2016

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

def dijkstra(g, s):
    q <- make_priority_queue(VERTEX.distance)
    for each vertex v in g.vertex:
        v.distance <- infinite
        v.predecessor ~> nil
        q.add(v)
    s.distance <- 0
    while not q.is_empty:
        u <- q.extract_min()
        for each adjacent vertex v of u:
            ...

def prim(g, s):
    q <- make_priority_queue(VERTEX.distance)
    for each vertex v in g.vertex:
        v.distance <- infinite
        v.predecessor ~> nil
        q.add(v)
    s.distance <- 0
    while not q.is_empty:
        u <- q.extract_min()
        for each adjacent vertex v of u:
            if v in q and weight(u, v) < v.distance:// <-------selection--------
            ...

Вычисления vertex.distance - вторая отличная точка.

person 象嘉道    schedule 28.06.2014

Алгоритм Дейкстра используется только для поиска кратчайшего пути.

В Минимальном связующем дереве (алгоритм Прима или Краскала) вы получаете минимальные границы с минимальным значением границы.

Например: - Рассмотрим ситуацию, когда вы не хотите создавать огромную сеть, для которой вам потребуется большое количество проводов, поэтому этот подсчет проводов можно выполнить с помощью Минимального связующего дерева (алгоритм Прима или Крускала) < / strong> (т.е. он даст вам минимальное количество проводов для создания огромного проводного сетевого соединения с минимальными затратами).

В то время как «алгоритм Дейкстра» будет использоваться для получения кратчайшего пути между двумя узлами при соединении любых узлов друг с другом.

person Dynamic Developer    schedule 06.12.2017

Алгоритм Дейкстры - это проблема кратчайшего пути с одним источником между узлами i и j, а алгоритм Прима - это проблема с минимальным остовным деревом. В этих алгоритмах используется концепция программирования под названием «жадный алгоритм».

Если вы проверите это понятие, посетите

  1. Лекция по жадному алгоритму: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/07-greedy.pdf.
  2. Минимальное связующее дерево: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/20-mst.pdf
  3. Кратчайший путь из одного источника: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/21-sssp.pdf.
person user1732445    schedule 10.12.2012

Самое простое объяснение: в Prims вы не указываете начальный узел, но в dijsktra вам (требуется начальный узел) нужно найти кратчайший путь от данного узла ко всем остальным узлам.

person Deepak Yadav    schedule 31.07.2018

@templatetypedef рассмотрел разницу между MST и кратчайшим путем. Я рассмотрел различие алгоритмов в другом So answer, продемонстрировав, что оба могут быть реализованы с использованием одного и того же общего алгоритма, который требует еще одного параметр в качестве входных данных: функция f(u,v). Разница между алгоритмом Прима и Дейкстры просто в том, какой f(u,v) вы используете.

person Shital Shah    schedule 30.12.2014

На уровне кода другое отличие - это API.

Вы инициализируете Prim с исходной вершиной, s, т.е. Prim.new(s); s может быть любой вершиной, и независимо от s конечный результат, то есть ребра минимального остовного дерева (MST), будет одинаковым. Чтобы получить ребра MST, мы вызываем метод edges().

Вы инициализируете Dijkstra с исходной вершиной, s, т.е. Dijkstra.new(s), которую вы хотите получить кратчайший путь / расстояние до всех остальных вершин. Конечные результаты - кратчайший путь / расстояние от s до всех остальных вершин; различаются в зависимости от s. Чтобы получить кратчайшие пути / расстояния от s до любой вершины, v, мы вызываем методы distanceTo(v) и pathTo(v) соответственно.

person nethsix    schedule 24.04.2016