图算法:Dijkstra算法

Dijkstra算法简单介绍

Dijkstra算法解决的是带权重的有向图上单源最短路径问题,该算法要求所有边的权重都为非负值。Dijkstra算法可以用于单个源点与单个目的点之间的最短路径问题,也可以用于单个源点和多个目的点之间的最短路径问题,在后者,该算法将生成一个“最短路径树”。没有使用最小优先队列的Dijkstra算法的时间复杂度为 O(|V|2) ,而后来相继有使用最小优先队列、二叉堆、d堆和 Fibonacci 堆等算法,很大程度上降低了时间复杂度。本文只讲述原始的Dijkstra算法和使用最小优先队列的Dijkstra算法。

The algorithm exists in many variants; Dijkstra’s original variant found the shortest path between two nodes, but a more common variant fixes a single node as the “source” node and finds shortest paths from the source to all other nodes in the graph, producing a shortest-path tree.

Dijkstra’s original algorithm does not use a min-priority queue and runs in time {\displaystyle O(|V|^{2})} O(|V|^{2}) (where {\displaystyle |V|} |V| is the number of nodes). The idea of this algorithm is also given in Leyzorek et al. 1957. The implementation based on a min-priority queue implemented by a Fibonacci heap and running in {\displaystyle O(|E|+|V|\log |V|)} O(|E|+|V|\log |V|) (where {\displaystyle |E|} |E| is the number of edges) is due to Fredman & Tarjan 1984. This is asymptotically the fastest known single-source shortest-path algorithm for arbitrary directed graphs with unbounded non-negative weights. However, specialized cases (such as bounded/integer weights, directed acyclic graphs etc.) can indeed be improved further as detailed in § Specialized variants. —— from WIKIPEDIA


1. 伪代码

In the following algorithm, the code u ← vertex in Q with min dist[u], searches for the vertex u in the vertex set Q that has the least dist[u] value. length(u, v) returns the length of the edge joining (i.e. the distance between) the two neighbor-nodes u and v. The variable alt on line 17 is the length of the path from the root node to the neighbor node v if it were to go through u. If this path is shorter than the current shortest path recorded for v, that current path is replaced with this alt path. The prev array is populated with a pointer to the “next-hop” node on the source graph to get the shortest route to the source. —— from WIKIPEDIA

function Dijkstra(Graph, source):

      create vertex set Q

       for each vertex v in Graph:             // Initialization
           dist[v] ← INFINITY                  // Unknown distance from source to v
           prev[v] ← UNDEFINED                 // Previous node in optimal path from source
         add v to Q                          // All nodes initially in Q (unvisited nodes)

      dist[source] ← 0                        // Distance from source to source

      while Q is not empty:
         u ← vertex in Q with min dist[u]    // Node with the least distance will be selected first
          remove u from Q 

         for each neighbor v of u:           // where v is still in Q.
              alt ← dist[u] + length(u, v)
             if alt < dist[v]:               // A shorter path to v has been found
                 dist[v] ← alt 
                 prev[v] ← u 

      return dist[], prev[]

如果需要找到到源点和某点 v 之间的最短路径,只要在上述的最短路径树上根据前驱结点回溯即可,即找到 pre[vi]=source

  S ← empty sequence
  u ← target
  while prev[u] is defined:                  // Construct the shortest path with a stack S
      insert u at the beginning of S         // Push the vertex onto the stack
      u ← prev[u]                            // Traverse from target to source
  insert u at the beginning of S             // Push the source onto the stack
使用最小优先队列

A min-priority queue is an abstract data type that provides 3 basic operations : add_with_priority(), decrease_priority() and extract_min(). As mentioned earlier, using such a data structure can lead to faster computing times than using a basic queue. Notably, Fibonacci heap (Fredman & Tarjan 1984) or Brodal queue offer optimal implementations for those 3 operations. As the algorithm is slightly different, we mention it here, in pseudo-code as well —— form WIKIPEDIA

  function Dijkstra(Graph, source):
      dist[source] ← 0                                    // Initialization

      create vertex set Q

      for each vertex v in Graph:           
          if v ≠ source
              dist[v] ← INFINITY                          // Unknown distance from source  v
              prev[v] ← UNDEFINED                         // Predecessor of v

         Q.add_with_priority(v, dist[v])


     while Q is not empty:                              // The main loop
         u ← Q.extract_min()                            // Remove and return best vertex
         for each neighbor v of u:                      // only v that is still in Q
             alt ← dist[u] + length(u, v) 
             if alt < dist[v]
                 dist[v] ← alt
                 prev[v] ← u
                 Q.decrease_priority(v, alt)

     return dist[], prev[]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值