# Shortest path: Dijstra algorithm

Keywords: Java less

## 1. Background

Full text according to Algorithms - Fourth Edition, Dijkstra (Dijkstra) algorithm, a single source shortest path algorithm.We abstract the problem into two steps: 1. Data structure abstraction 2. Implementation.They correspond to Chapter Two and Chapter Three respectively.

## 2. Algorithmic Analysis

### 2.1 Data Structure

#### Vertex+Edge->Graph.Note: The limitations of the Dijkstra algorithm:

• 1. Edges have weight and are not negative
• 2. Edge Directed

#### 2.1.1 Weighted Directed Edges

DirectedEdge, API abstracted as follows:

 Method describe DirectedEdge(int v, int w, double weight) Construct Edges double weight() Edge weight int from() The starting point of the edge int to() End point of edge

#### 2.1.2 Weighted Directed Graph

EdgeWeightedDigraph, API abstracted as follows:

 Method describe EdgeWeightedDigraph(In in) Construct a graph from an input stream int V() Total number of vertices int E() Total Edges void addEdge(DirectedEdge e) Add Edge e to the diagram Iterable adj(int v) Edges indicated from vertex v (contiguity table, a hash list, key=vertex, value=vertex-indicated edge chain list) Iterable edges() All edges in the graph

#### 2.1.3 Shortest Path

DijkstraSP, API abstracted as follows:

 Method describe DijkstraSP(EdgeWeightedDigraph G, int s) Construct Shortest Path Tree double distTo(int v) Distance from vertex s->v to initialize infinity boolean hasPathTo(int v) Is there a path to vertex s->v Iterable pathTo(int v) S->v path, does not exist as null

Elements:

Edges in the shortest path tree (DirectedEdge[] edgeTo):

The edgeTo[v] represents the edge in the tree that connects V to the parent node (the last array of edges of the shortest path). Each vertex has such an edge that makes up the shortest path tree.

Distance from origin to vertex: array double[] distTo indexed by vertices:

distTo[v] represents the shortest distance from the origin to vertex v.

Index Minimum Priority Queue: IndexMinPQ<Double> pq:

int[] pq: index binary heap (element=vertex v, corresponding to keys[v]): array is inserted from pq[0] on behalf of origin and other vertices from pq[1]

Key[] keys: The shortest distance an ordered array of elements (assigned as a subscript according to the pq value) is stored to a vertex

### 2.2 algorithm core

Calculate the shortest path in three steps:

• 1. Select the minimum node vertex at a time: If so?Use the minimum heap sorting, each time you pick up the top element of the heap.
• 2. Traverse all edges emitted from vertices
• 3. Relax

## 3. Specific implementation

### 3.1 Construction

#### 3.1.1 Element Iterator

`Because of traversal requirements, the Bag<Item>class is defined here to implement the Iterable<Item>iterator interface, where Item is an element.Is the basic implementation of an iterator for a simple element.`
``````  1 package study.algorithm.base;
2
3 import java.util.Iterator;
4 import java.util.NoSuchElementException;
5
6 /**
7  *  The {@code Bag} class represents a bag (or multiset) of
8  *  generic items. It supports insertion and iterating over the
9  *  items in arbitrary order.
10  *  <p>
11  *  This implementation uses a singly linked list with a static nested class Node.
13  *  textbook that uses a non-static nested class.
14  *  See {@link ResizingArrayBag} for a version that uses a resizing array.
15  *  The <em>add</em>, <em>isEmpty</em>, and <em>size</em> operations
16  *  take constant time. Iteration takes time proportional to the number of items.
17  *  <p>
18  *  For additional documentation, see <a href="https://algs4.cs.princeton.edu/13stacks">Section 1.3</a> of
19  *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
20  *
21  *  @author Robert Sedgewick
22  *  @author Kevin Wayne
23  *
24  *  @param <Item> the generic type of an item in this bag
25  */
26 public class Bag<Item> implements Iterable<Item> {
27     /**
28      * First Node
29      */
30     private Node<Item> first;
31     /**
32      * Number of elements
33      */
34     private int n;
35
36     /**
38      * @param <Item>
39      */
40     private static class Node<Item> {
41         private Item item;
42         private Node<Item> next;
43     }
44
45     /**
46      * Initialize an empty package
47      */
48     public Bag() {
49         first = null;
50         n = 0;
51     }
52
53     /**
54      * Returns true if this bag is empty.
55      *
56      * @return {@code true} if this bag is empty;
57      *         {@code false} otherwise
58      */
59     public boolean isEmpty() {
60         return first == null;
61     }
62
63     /**
64      * Returns the number of items in this bag.
65      *
66      * @return the number of items in this bag
67      */
68     public int size() {
69         return n;
70     }
71
72     /**
73      * Adds the item to this bag.
74      *
75      * @param  item the item to add to this bag
76      */
77     public void add(Item item) {
78         // Keep the old first node
79         Node<Item> oldfirst = first;
80         // Construct a new first node
81         first = new Node<Item>();
82         // item Is New First Node item
83         first.item = item;
84         // New Node's next Node Points to Old First Node
85         first.next = oldfirst;
86         n++;
87     }
88
89
90     /**
91      * Returns an iterator that iterates over the items in this bag in arbitrary order.
92      *
93      * @return an iterator that iterates over the items in this bag in arbitrary order
94      */
95     @Override
96     public Iterator<Item> iterator()  {
98     }
99
100     /**
101      * Link iterator, remove not supported
102      */
103     private class LinkedIterator implements Iterator<Item> {
104         private Node<Item> current;
105
107             current = first;
108         }
109
110         @Override
111         public boolean hasNext()  { return current != null;                     }
112         @Override
113         public void remove()      { throw new UnsupportedOperationException();  }
114
115         @Override
116         public Item next() {
117             if (!hasNext()) {
118                 throw new NoSuchElementException();
119             }
120             Item item = current.item;
121             // Next Node
122             current = current.next;
123             return item;
124         }
125     }
126
127     /**
128      * Unit tests the {@code Bag} data type.
129      *
130      * @param args the command-line arguments
131      */
132     public static void main(String[] args) {
133         Bag<String> bag = new Bag<String>();
134         while (!StdIn.isEmpty()) {
137         }
138
139         StdOut.println("size of bag = " + bag.size());
140         for (String s : bag) {
141             StdOut.println(s);
142         }
143     }
144
145 }``````

3.1.2 Specific Constructions

1. Initialize the diagram from the input stream in the format of the input stream (comments in parentheses, not in the actual file):

8 (Number of vertices)
15 (Number of Edges)
45 0.35 (edge 4->5 weight=0.35)
5 4 0.35
4 7 0.37
5 7 0.28
7 5 0.28
5 1 0.32
0 4 0.38
0 2 0.26
7 3 0.39
1 3 0.29
2 7 0.34
6 2 0.40
3 6 0.52
6 0 0.58
6 4 0.93

In the following figure, the public EdgeWeightedDigraph (In) construction method, core:

Adds weighted edges to the adjacency table where vertices are array subscripts.

``````  1 package study.algorithm.graph;
2
3 import study.algorithm.base.*;
4
5 import java.util.NoSuchElementException;
6
7 /***
8  * @Description Edge Weighted Directed Graph
9  * @author denny.zhang
10  * @date 2020/4/24 9:58 morning
11  */
12 public class EdgeWeightedDigraph {
13     private static final String NEWLINE = System.getProperty("line.separator");
14
15     /**
16      * Total number of vertices
17      */
18     private final int V;
19     /**
20      * Total Edges
21      */
22     private int E;
23     /**
25      */
27
28     /**
29      * Initialize the diagram from the input stream format:
30      * 8(Number of vertices)
31      * 15(Total Edges)
32      * 4 5 0.35(4->5 weights 0.35 per edge)
33      * 5 4 0.35
34      * 4 7 0.37
35      * ...
36      *
37      * @param  in the input stream
38      * @throws IllegalArgumentException if {@code in} is {@code null}
39      * @throws IllegalArgumentException if the endpoints of any edge are not in prescribed range
40      * @throws IllegalArgumentException if the number of vertices or edges is negative
41      */
42     public EdgeWeightedDigraph(In in) {
43         if (in == null) {
44             throw new IllegalArgumentException("argument is null");
45         }
46         try {
47             // 1.Number of read vertices
53             adj = (Bag<DirectedEdge>[]) new Bag[V];
54             for (int v = 0; v < V; v++) {
56             }
57             // 2.Number of read edges
59             62             for (int i = 0; i < E; i++) {
71             }
72         }
73         catch (NoSuchElementException e) {
74             throw new IllegalArgumentException("invalid input format in EdgeWeightedDigraph constructor", e);
75         }
76     }
77
78     /**
79      * Number of vertices
80      *
81      * @return the number of vertices in this edge-weighted digraph
82      */
83     public int V() {
84         return V;
85     }
86
87     /**
88      * Number of Edges
89      *
90      * @return the number of edges in this edge-weighted digraph
91      */
92     public int E() {
93         return E;
94     }
95
106     /**
107      * Add an edge to the diagram
108      *
109      * @param  e the edge
110      * @throws IllegalArgumentException unless endpoints of edge are between {@code 0}
111      *         and {@code V-1}
112      */
113     public void addEdge(DirectedEdge e) {
114         // Starting point of edge
115         int v = e.from();
116         // End point of edge
117         int w = e.to();120         // Starting point v Add an edge to the adjacency table of
122         // Total Edges+1
123         E++;
124     }
125
126
127     /**
128      * Returns all iterative edges indicated from vertex V (adjacency table)
129      *
130      * @param  v the vertex
131      * @return the directed edges incident from vertex {@code v} as an Iterable
132      * @throws IllegalArgumentException unless {@code 0 <= v < V}
133      */
134     public Iterable<DirectedEdge> adj(int v) {
135         validateVertex(v);
137     }
138
139     /**
140      * Return all directed edges
141      *
142      * @return all edges in this edge-weighted digraph, as an iterable
143      */
144     public Iterable<DirectedEdge> edges() {
145         Bag<DirectedEdge> list = new Bag<DirectedEdge>();
146         // Traverse all vertices
147         for (int v = 0; v < V; v++) {
148             // Contiguity table for each vertex (pointing out edges)
149             for (DirectedEdge e : adj(v)) {
150                 // Point out edges list
152             }
153         }
154         return list;
155     }
156
157     /**
158      * Returns a string representation of this edge-weighted digraph.
159      *
160      * @return the number of vertices <em>V</em>, followed by the number of edges <em>E</em>,
161      *         followed by the <em>V</em> adjacency lists of edges
162      */
163     @Override
164     public String toString() {
165         StringBuilder s = new StringBuilder();
166         s.append(V + " " + E + NEWLINE);
167         for (int v = 0; v < V; v++) {
168             s.append(v + ": ");
169             for (DirectedEdge e : adj[v]) {
170                 s.append(e + "  ");
171             }
172             s.append(NEWLINE);
173         }
174         return s.toString();
175     }
176
177     /**
178      * Unit tests the {@code EdgeWeightedDigraph} data type.
179      *
180      * @param args the command-line arguments
181      */
182     public static void main(String[] args) {
183         In in = new In(args[0]);
184         EdgeWeightedDigraph G = new EdgeWeightedDigraph(in);
185         StdOut.println(G);
186     }
187
188 }``````

### 3.2 Calculate Shortest Path

#### 3.2.1 Index Priority Queue

``````  1 package study.algorithm.base;
2
3 import java.util.Iterator;
4 import java.util.NoSuchElementException;
5
6 /**
7  * Index Minimum Priority Queue
8  *
9  * @param <Key>
10  */
11 public class IndexMinPQ<Key extends Comparable<Key>> implements Iterable<Integer> {
12     /**
13      * Maximum number of elements
14      */
15     private int maxN;
16     /**
17      * Number of elements
18      */
19     private int n;
20     /**
21      * Index binary heap (element = vertex v, corresponding to keys[v]): pq[0] represents the origin, other vertices are inserted from pq[1]
22      */
23     private int[] pq;
24     /**
25      * The position of the element marked with index I in the binary heap.Inverted array of PQ (qp[index]=i): qp[pq[i] = pq[qp[i]] = I
26      */
27     private int[] qp;
28
29     /**
30      * Ordered array of elements (assigned by index of pq)
31      */
32     private Key[] keys;
33
34     /**
35      * Initialize an empty index priority queue, index range: 0 ~ maxN-1
36      *
37      * @param  maxN the keys on this priority queue are index from {@code 0}
38      *         {@code maxN - 1}
39      * @throws IllegalArgumentException if {@code maxN < 0}
40      */
41     public IndexMinPQ(int maxN) {
42         if (maxN < 0) throw new IllegalArgumentException();
43         this.maxN = maxN;
44         // Initially there are 0 elements
45         n = 0;
46         // Initialization key array length is maxN + 1
47         keys = (Key[]) new Comparable[maxN + 1];
48         // Initialization"Key-Value Pairs"Array length is maxN + 1
49         pq   = new int[maxN + 1];
50         // Initialization"Value Key Pair"Array length is maxN + 1
51         qp   = new int[maxN + 1];
52         // Traverse to"Value Key Pair"Array assignment-1，Follow-up as long as!=-1,That is, contains i
53         for (int i = 0; i <= maxN; i++)
54             qp[i] = -1;
55     }
56
57     /**
58      * Returns true if this priority queue is empty.
59      *
60      * @return {@code true} if this priority queue is empty;
61      *         {@code false} otherwise
62      */
63     public boolean isEmpty() {
64         return n == 0;
65     }
66
67     /**
68      * Is {@code i} an index on this priority queue?
69      *
70      * @param  i an index
71      * @return {@code true} if {@code i} is an index on this priority queue;
72      *         {@code false} otherwise
73      * @throws IllegalArgumentException unless {@code 0 <= i < maxN}
74      */
75     public boolean contains(int i) {
76         validateIndex(i);
77         return qp[i] != -1;
78     }
79
80     /**
81      * Returns the number of keys on this priority queue.
82      *
83      * @return the number of keys on this priority queue
84      */
85     public int size() {
86         return n;
87     }
88
89     /**
90      * Insert an element to associate element key with index i
91      *
92      * @param  i an index
93      * @param  key the key to associate with index {@code i}
94      * @throws IllegalArgumentException unless {@code 0 <= i < maxN}
95      * @throws IllegalArgumentException if there already is an item associated
96      *         with index {@code i}
97      */
98     public void insert(int i, Key key) {
99         validateIndex(i);
100         if (contains(i)) throw new IllegalArgumentException("index is already in the priority queue");
101         // Number of elements+1
102         n++;
103         // Index is i Binary heap location is n
104         qp[i] = n;
105         // Insert new element at bottom of binary heap, value=i
106         pq[n] = i;
107         // Indexes i Corresponding element assignment
108         keys[i] = key;
109         // Last element floating up in binary heap (small value floating up)
110         swim(n);
111     }
112
113     /**
114      * Returns the index of the smallest element
115      *
116      * @return an index associated with a minimum key
117      * @throws NoSuchElementException if this priority queue is empty
118      */
119     public int minIndex() {
120         if (n == 0) throw new NoSuchElementException("Priority queue underflow");
121         return pq[1];
122     }
123
124     /**
125      * Return the minimum element (key)
126      *
127      * @return a minimum key
128      * @throws NoSuchElementException if this priority queue is empty
129      */
130     public Key minKey() {
131         if (n == 0) throw new NoSuchElementException("Priority queue underflow");
132         return keys[pq[1]];
133     }
134
135     /**
136      * Delete the minimum key and return the minimum value
137      *
138      * @return an index associated with a minimum key
139      * @throws NoSuchElementException if this priority queue is empty
140      */
141     public int delMin() {
142         if (n == 0) throw new NoSuchElementException("Priority queue underflow");
143         // pq[1]That is, the minimum value of the index
144         int min = pq[1];
145         // Swap the first and last elements
146         exch(1, n--);
147         // Drop the first element in exchange
148         sink(1);
149         // After verification sinks, the last element is the minimum value
150         assert min == pq[n+1];
151         // Restore the initial value,-1 That means the element has been deleted
152         qp[min] = -1;        // delete
153         // Convenient garbage collection
154         keys[min] = null;
155         // Last element (index) assignment-1
156         pq[n+1] = -1;        // not needed
157         return min;
158     }
159
160     /**
161      * Returns the key associated with index {@code i}.
162      *
163      * @param  i the index of the key to return
164      * @return the key associated with index {@code i}
165      * @throws IllegalArgumentException unless {@code 0 <= i < maxN}
166      * @throws NoSuchElementException no key is associated with index {@code i}
167      */
168     public Key keyOf(int i) {
169         validateIndex(i);
170         if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
171         else return keys[i];
172     }
173
174     /**
175      * Change the key associated with index {@code i} to the specified value.
176      *
177      * @param  i the index of the key to change
178      * @param  key change the key associated with index {@code i} to this key
179      * @throws IllegalArgumentException unless {@code 0 <= i < maxN}
180      * @throws NoSuchElementException no key is associated with index {@code i}
181      */
182     public void changeKey(int i, Key key) {
183         validateIndex(i);
184         if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
185         keys[i] = key;
186         swim(qp[i]);
187         sink(qp[i]);
188     }
189
190     /**
191      * Change the key associated with index {@code i} to the specified value.
192      *
193      * @param  i the index of the key to change
194      * @param  key change the key associated with index {@code i} to this key
195      * @throws IllegalArgumentException unless {@code 0 <= i < maxN}
196      * @deprecated Replaced by {@code changeKey(int, Key)}.
197      */
198     @Deprecated
199     public void change(int i, Key key) {
200         changeKey(i, key);
201     }
202
203     /**
204      * Decrease the value of index i to key
205      * To update:
206      * 1.Element array keys[]
207      * 2.Small Top Binary Heap pq[]
208      *
209      * @param  i the index of the key to decrease
210      * @param  key decrease the key associated with index {@code i} to this key
211      * @throws IllegalArgumentException unless {@code 0 <= i < maxN}
212      * @throws IllegalArgumentException if {@code key >= keyOf(i)}
213      * @throws NoSuchElementException no key is associated with index {@code i}
214      */
215     public void decreaseKey(int i, Key key) {
216         validateIndex(i);
217         if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
218         // key Same value, error
219         if (keys[i].compareTo(key) == 0)
220             throw new IllegalArgumentException("Calling decreaseKey() with a key equal to the key in the priority queue");
221         // key Greater than current value, error
222         if (keys[i].compareTo(key) < 0)
223             throw new IllegalArgumentException("Calling decreaseKey() with a key strictly greater than the key in the priority queue");
224         // key Smaller than the current value, key Assignment in
225         keys[i] = key;
226         // Small values float up ( qp[i]=Indexes i In Binary Heap pq[]Position in)
227         swim(qp[i]);
228     }
229
230     /**
231      * Increase the key associated with index {@code i} to the specified value.
232      *
233      * @param  i the index of the key to increase
234      * @param  key increase the key associated with index {@code i} to this key
235      * @throws IllegalArgumentException unless {@code 0 <= i < maxN}
236      * @throws IllegalArgumentException if {@code key <= keyOf(i)}
237      * @throws NoSuchElementException no key is associated with index {@code i}
238      */
239     public void increaseKey(int i, Key key) {
240         validateIndex(i);
241         if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
242         if (keys[i].compareTo(key) == 0)
243             throw new IllegalArgumentException("Calling increaseKey() with a key equal to the key in the priority queue");
244         if (keys[i].compareTo(key) > 0)
245             throw new IllegalArgumentException("Calling increaseKey() with a key strictly less than the key in the priority queue");
246         keys[i] = key;
247         sink(qp[i]);
248     }
249
250     /**
251      * Remove the key associated with index {@code i}.
252      *
253      * @param  i the index of the key to remove
254      * @throws IllegalArgumentException unless {@code 0 <= i < maxN}
255      * @throws NoSuchElementException no key is associated with index {@code i}
256      */
257     public void delete(int i) {
258         validateIndex(i);
259         if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
260         int index = qp[i];
261         exch(index, n--);
262         swim(index);
263         sink(index);
264         keys[i] = null;
265         qp[i] = -1;
266     }
267
268     // throw an IllegalArgumentException if i is an invalid index
269     private void validateIndex(int i) {
270         if (i < 0) throw new IllegalArgumentException("index is negative: " + i);
271         if (i >= maxN) throw new IllegalArgumentException("index >= capacity: " + i);
272     }
273
274    /***************************************************************************
275     * General helper functions.
276     ***************************************************************************/
277     private boolean greater(int i, int j) {
278         return keys[pq[i]].compareTo(keys[pq[j]]) > 0;
279     }
280
281     private void exch(int i, int j) {
282         int swap = pq[i];
283         pq[i] = pq[j];
284         pq[j] = swap;
285         qp[pq[i]] = i;
286         qp[pq[j]] = j;
287     }
288
289
290    /***************************************************************************
291     * Heap helper functions.
292     ***************************************************************************/
293     private void swim(int k) {
294         // If the parent node value is larger than the current node value, swap, and the parent node is the current node, polling.That is, small values float up.
295         while (k > 1 && greater(k/2, k)) {
296             exch(k, k/2);
297             k = k/2;
298         }
299     }
300
301     private void sink(int k) {
302         while (2*k <= n) {
303             int j = 2*k;
304             if (j < n && greater(j, j+1)) j++;
305             if (!greater(k, j)) break;
306             exch(k, j);
307             k = j;
308         }
309     }
310
311
312    /***************************************************************************
313     * Iterators.
314     ***************************************************************************/
315
316     /**
317      * Returns an iterator that iterates over the keys on the
318      * priority queue in ascending order.
319      * The iterator doesn't implement {@code remove()} since it's optional.
320      *
321      * @return an iterator that iterates over the keys in ascending order
322      */
323     @Override
324     public Iterator<Integer> iterator() { return new HeapIterator(); }
325
326     private class HeapIterator implements Iterator<Integer> {
327         // create a new pq
328         private IndexMinPQ<Key> copy;
329
330         // add all elements to copy of heap
331         // takes linear time since already in heap order so no keys move
332         public HeapIterator() {
333             copy = new IndexMinPQ<Key>(pq.length - 1);
334             for (int i = 1; i <= n; i++)
335                 copy.insert(pq[i], keys[pq[i]]);
336         }
337
338         @Override
339         public boolean hasNext()  { return !copy.isEmpty();                     }
340         @Override
341         public void remove()      { throw new UnsupportedOperationException();  }
342
343         @Override
344         public Integer next() {
345             if (!hasNext()) throw new NoSuchElementException();
346             return copy.delMin();
347         }
348     }
349
350
351     /**
352      * Unit tests the {@code IndexMinPQ} data type.
353      *
354      * @param args the command-line arguments
355      */
356     public static void main(String[] args) {
357         // insert a bunch of strings
358         String[] strings = { "it", "was", "the", "best", "of", "times", "it", "was", "the", "worst" };
359
360         IndexMinPQ<String> pq = new IndexMinPQ<String>(strings.length);
361         for (int i = 0; i < strings.length; i++) {
362             pq.insert(i, strings[i]);
363         }
364
365         // delete and print each key
366         while (!pq.isEmpty()) {
367             int i = pq.delMin();
368             StdOut.println(i + " " + strings[i]);
369         }
370         StdOut.println();
371
372         // reinsert the same strings
373         for (int i = 0; i < strings.length; i++) {
374             pq.insert(i, strings[i]);
375         }
376
377         // print each key using the iterator
378         for (int i : pq) {
379             StdOut.println(i + " " + strings[i]);
380         }
381         while (!pq.isEmpty()) {
382             pq.delMin();
383         }
384
385     }
386 }``````

#### 3.2.2 Shortest Path

``````  1 package study.algorithm.graph;
2
3 import study.algorithm.base.In;
4 import study.algorithm.base.IndexMinPQ;
5 import study.algorithm.base.Stack;
6 import study.algorithm.base.StdOut;
7
8 /***
9  * @Description Single Start Shortest Path Tree for Weighted Directed Graph with Nonnegative Edge Weights
10  * @author denny.zhang
11  * @date 2020/4/23 11:29 morning
12  */
13 public class DijkstraSP {
14
15     /**
16      * Shortest path array, element: shortest path to all vertices
17      */
18     private double[] distTo;
19
20     /**
21      * Directed edge array: the last edge array of the shortest path
22      */
23     private DirectedEdge[] edgeTo;
24
25     /**
26      * Vertex as subscript, index minimum priority queue
27      */
28     private IndexMinPQ<Double> pq;
29
30     /**
31      * Compute the Shortest Path Edge Weight Graph from Origin S to all other vertices
32      *
33      * @param  G the edge-weighted digraph Edge Weight Graph
34      * @param  s the source vertex origin
35      * @throws IllegalArgumentException if an edge weight is negative
36      * @throws IllegalArgumentException unless {@code 0 <= s < V}
37      */
38     public DijkstraSP(EdgeWeightedDigraph G, int s) {
39         // Negative Weight Check
40         for (DirectedEdge e : G.edges()) {
41             if (e.weight() < 0) {
42                 throw new IllegalArgumentException("edge " + e + " has negative weight");
43             }
44         }
45         // Shortest path array length=Number of vertices
46         distTo = new double[G.V()];
47         // Construct an array of shortest path edges whose length is the total number of vertices
48         edgeTo = new DirectedEdge[G.V()];
49         // Check Origin Value
50         validateVertex(s);
51         // Initialize all vertices to infinity
52         for (int v = 0; v < G.V(); v++) {
53             distTo[v] = Double.POSITIVE_INFINITY;
54         }
55         // Minimum path initialized to origin is 0
56         distTo[s] = 0.0;
57
58         // Construct an index minimum priority queue with a length of total vertices
59         pq = new IndexMinPQ<Double>(G.V());
60         // Insert the origin, path 0
61         pq.insert(s, distTo[s]);
62         // As long as the queue is not empty(From top to bottom, iterate through in sequence pq[])，
63         while (!pq.isEmpty()) {
64             // Remove Minimum key(That is pq[1])，And returns the minimum value (vertex)
65             int v = pq.delMin();
66             // Traversal vertices v Contiguity table for each edge
67             for (DirectedEdge e : G.adj(v)) {
68                 // Relax the edges
69                 relax(e);
70             }
71         }
72
73         // check
74         assert check(G, s);
75     }
76
77     /**
78      * Relax and update pq
79      * @param e
80      */
81     private void relax(DirectedEdge e) {
82         // Start point, end point
83         int v = e.from(), w = e.to();
84         // If Origin to End w Distance of > Origin to Start v Distance of+Edge weights indicate origin to w Relaxed
85         if (distTo[w] > distTo[v] + e.weight()) {
86             // Latest Distance
87             distTo[w] = distTo[v] + e.weight();
88             // To End w Edge assignment to new edge
89             edgeTo[w] = e;
90             // If the priority queue already contains an end point w
91             if (pq.contains(w)) {
92                 // The comparison subscript is w Of key If>Current path (that is, the current value is smaller than the median value of the queue), reordering
93                 pq.decreaseKey(w, distTo[w]);
94             } else {
95                 // Do not include, insert, and sort
96                 pq.insert(w, distTo[w]);
97             }
98         }
99     }
100
101     /**
102      * s->v Shortest path
103      * @param  v the destination vertex
104      * @return the length of a shortest path from the source vertex {@code s} to vertex {@code v};
105      *         {@code Double.POSITIVE_INFINITY} if no such path
106      * @throws IllegalArgumentException unless {@code 0 <= v < V}
107      */
108     public double distTo(int v) {
109         validateVertex(v);
110         return distTo[v];
111     }
112
113     /**
114      * s->v Is it reachable
115      *
116      * @param  v the destination vertex
117      * @return {@code true} if there is a path from the source vertex
118      *         {@code s} to vertex {@code v}; {@code false} otherwise
119      * @throws IllegalArgumentException unless {@code 0 <= v < V}
120      */
121     public boolean hasPathTo(int v) {
122         validateVertex(v);
123         return distTo[v] < Double.POSITIVE_INFINITY;
124     }
125
126     /**
127      * s->v Minimum Iterable Edge (1->2->3)
128      *
129      * @param  v the destination vertex
130      * @return a shortest path from the source vertex {@code s} to vertex {@code v}
131      *         as an iterable of edges, and {@code null} if no such path
132      * @throws IllegalArgumentException unless {@code 0 <= v < V}
133      */
134     public Iterable<DirectedEdge> pathTo(int v) {
135         validateVertex(v);
136         if (!hasPathTo(v)) {
137             return null;
138         }
139         // Iterable Directed Edge Stack
140         Stack<DirectedEdge> path = new Stack<DirectedEdge>();
141         // e Is Vertex v The last edge of the shortest path tree, tracing back to the last vertex 3 along the edge->2->1
142         for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) {
143             // Stack
144             path.push(e);
145         }
146         return path;
147     }
148
149
150     // check optimality conditions:
151     // (i) for all edges e:            distTo[e.to()] <= distTo[e.from()] + e.weight()
152     // (ii) for all edge e on the SPT: distTo[e.to()] == distTo[e.from()] + e.weight()
153     private boolean check(EdgeWeightedDigraph G, int s) {
154
155         // Check edge weight is not negative
156         for (DirectedEdge e : G.edges()) {
157             if (e.weight() < 0) {
158                 System.err.println("negative edge weight detected");
159                 return false;
160             }
161         }
162
163         // Vertex-to-vertex path is 0 and vertex-to-vertex edge is empty
164         if (distTo[s] != 0.0 || edgeTo[s] != null) {
165             System.err.println("distTo[s] and edgeTo[s] inconsistent");
166             return false;
167         }
168         // Traversal vertices
169         for (int v = 0; v < G.V(); v++) {
170             // Start Skip
171             if (v == s) {
172                 continue;
173             }
174             // To vertex v The last edge is empty (unreachable) and reaches the vertex v The shortest path does not conflict with infinity (that is, it has value)
175             if (edgeTo[v] == null && distTo[v] != Double.POSITIVE_INFINITY) {
176                 System.err.println("distTo[] and edgeTo[] inconsistent");
177                 return false;
178             }
179         }
180
181         // Verify all edges are not relaxed
182         for (int v = 0; v < G.V(); v++) {
183             // Traversal vertices v Adjacent edges of
184             for (DirectedEdge e : G.adj(v)) {
185                 int w = e.to();
186                 // Check Relaxation
187                 if (distTo[v] + e.weight() < distTo[w]) {
188                     System.err.println("edge " + e + " not relaxed");
189                     return false;
190                 }
191             }
192         }
193
194         // Check Shortest Path Tree: Satisfy distTo[w] == distTo[v] + e.weight()
195         for (int w = 0; w < G.V(); w++) {
196             // Skip unreachable vertices
197             if (edgeTo[w] == null) {
198                 continue;
199             }
200             // Last Edge
201             DirectedEdge e = edgeTo[w];
202             // Starting point
203             int v = e.from();
204             //End
205             if (w != e.to()) {
206                 return false;
207             }
208             // Check: Shortest-path Tree, Start-point Path+weight=End Path
209             if (distTo[v] + e.weight() != distTo[w]) {
210                 System.err.println("edge " + e + " on shortest path not tight");
211                 return false;
212             }
213         }
214         return true;
215     }
216
217     // throw an IllegalArgumentException unless {@code 0 <= v < V}
218     private void validateVertex(int v) {
219         int V = distTo.length;
220         if (v < 0 || v >= V) {
221             throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));
222         }
223     }
224
225     /**
226      * Unit tests the {@code DijkstraSP} data type.
227      *
228      * @param args the command-line arguments
229      */
230     public static void main(String[] args) {
231         // Diagram file name
232         In in = new In(args[0]);
233         // Constructing Edge Weighted Directed Graph
234         EdgeWeightedDigraph G = new EdgeWeightedDigraph(in);
235         // vertex
236         int s = Integer.parseInt(args[1]);
237
238         // Calculate Shortest Path
239         DijkstraSP sp = new DijkstraSP(G, s);
240
241         // Traverse all vertices
242         for (int t = 0; t < G.V(); t++) {
243             // accessible
244             if (sp.hasPathTo(t)) {
245                 // Origin to t Path Length
246                 StdOut.printf("%d to %d (%.2f)  ", s, t, sp.distTo(t));
247                 // Origin to t Path Map
248                 for (DirectedEdge e : sp.pathTo(t)) {
249                     StdOut.print(e + "   ");
250                 }
251                 // Line Break
252                 StdOut.println();
253             }
254             // Unreachable
255             else {
256                 StdOut.printf("%d to %d         no path\n", s, t);
257             }
258         }
259     }
260
261 }``````

4. Test results

4.1 Test Preparation

A file, tinyEWD.txt, exists locally as follows:

```8
15
4 5 0.35
5 4 0.35
4 7 0.37
5 7 0.28
7 5 0.28
5 1 0.32
0 4 0.38
0 2 0.26
7 3 0.39
1 3 0.29
2 7 0.34
6 2 0.40
3 6 0.52
6 0 0.58
6 4 0.93```

4.2 Test

Run DijkstraSP locally and configure the running parameters. Take idea for example: the first parameter is the file address, the second parameter represents the origin 0, calculates the "shortest path" edge weight graph from the origin (vertex 0) to all other vertices:

The shortest path to run is as follows:

Posted by robdavies on Wed, 06 May 2020 20:07:23 -0700