The shortest distance between points. The shortest path on earth and on the map

  • 19.07.2021

DISTANCE, distances, cf. 1. The space separating two points, the gap between something. The shortest distance between two points in a straight line. Lives from us at a distance of two kilometers. “The commandant allowed them to come as close as possible ... Ushakov's Explanatory Dictionary

distance- noun, p., uptr. often Morphology: (no) what? distance, what? distance, (see) what? distance than? distance, about what? about distance; pl. what? distance, (no) what? distances, what? distances, (see) what? distance than? distances ... Dmitriev's Explanatory Dictionary

distance- I am; Wed The space separating two points, two objects, etc., the gap between whom, than l. The shortest r. between two points. R. from home to school. Move to the close river. At a distance of a meter, outstretched hands. Know l., Feel l. on… … encyclopedic Dictionary

distance- I am; Wed see also. distance a) The space separating two points, two objects, etc., the gap between whom, than l. Shortest distance between two points. Distance / distance from home to school. Get close ... Dictionary of many expressions

GEOMETRY- a branch of mathematics dealing with the study of the properties of various shapes (points, lines, angles, two-dimensional and three-dimensional objects), their size and relative position. For the convenience of teaching, geometry is subdivided into planimetry and stereometry. V… … Collier's Encyclopedia

Navigation*

Navigation- the department of navigation (see), concluding a statement of ways to determine the location of the ship at sea, using a compass and log (see). To determine the place of the ship on the sea, it means to draw on the map the point at which the ship is at the moment. ... ... Encyclopedic Dictionary of F.A. Brockhaus and I.A. Efron

COGEN- (Cohen) Hermann (1842 1918) German philosopher, founder and most prominent representative of the Marburg school of neo-Kantianism. Major works: 'Theory of Kant's Experience' (1885), 'Kant's Justification of Ethics' (1877),' Kant's Justification of Aesthetics' (1889), 'Logic ... ...

Kant Immanuel- Life path and works of Kant Immanuel Kant was born in Konigsberg (now Kaliningrad) in East Prussia in 1724. His father was a saddler, and his mother was a housewife, their six children did not live to mature age. Kant always remembered his parents from ... ... Western philosophy from the beginnings to the present day

KANT'S CRITICAL PHILOSOPHY: A TEACHING ABOUT ABILITIES- (La philosophie critique de Kant: Doctrines des facultes, 1963) by Deleuze. Describing the transcendental method in the introduction, Deleuze notes that Kant understands philosophy as the science of the relationship of all knowledge to essential goals ... ... History of Philosophy: An Encyclopedia

Farm principle- the basic principle of geometric optics (see Geometric optics). The simplest form of a phytoplankton is the statement that a ray of light always propagates in space between two points along the path along which the time of its passage is less than ... Great Soviet Encyclopedia

Having marked two points on the blackboard with chalk, the teacher offers the young student a task: to draw the shortest path between the two points.

The student, having thought, carefully draws a winding line between them.

- This is the shortest path! - the teacher is surprised. - Who taught you that?

- My father. He's a taxi driver.

The drawing of a naive schoolboy is, of course, anecdotal, but wouldn't you smile if you were told that the dotted arc in Fig. 1 is the shortest route from the Cape of Good Hope to the southern tip of Australia!

Even more striking is the following statement: depicted in fig. 2 the roundabout route from Japan to the Panama Canal is shorter than the straight line drawn between them on the same map!

Rice. 1. On a nautical chart, the shortest route from the Cape of Good Hope to the southern tip of Australia is indicated not by a straight line ("loxodrome"), but by a curve ("orthodrome")


All this looks like a joke, and yet before you are indisputable truths, well known to cartographers.




Rice. 2. It seems incredible that the curved path connecting Yokohama to the Panama Canal on a nautical chart is shorter than a straight line drawn between the same points


To clarify the issue, I will have to say a few words about maps in general and about sea maps in particular. The depiction of parts of the earth's surface on paper is not easy even in principle, because the Earth is a sphere, and it is known that no part of a spherical surface can be deployed on a plane without folds and breaks. Inevitably, you have to put up with the inevitable distortions on the cards. Many ways of drawing maps have been invented, but all maps are not free from flaws: some have distortions of one kind, others of a different kind, but there are no maps without distortions at all.

Sailors use maps drawn according to the method of the old Dutch cartographer and mathematician of the 16th century. Mercator. This method is called "mercator projection". It is easy to recognize a nautical chart by its rectangular grid: the meridians are depicted on it in the form of a series of parallel straight lines; the circles of latitude are also straight lines perpendicular to the first (see Fig. 5).

Imagine now that you want to find the shortest path from one ocean port to another, lying on the same parallel. On the ocean, all paths are accessible, and it is always possible to travel along the shortest path there if you know how it runs. In our case, it is natural to think that the shortest path goes along the parallel on which both ports lie: after all, on the map it is a straight line, and what can be shorter than a straight path! But we are wrong: the parallel path is by no means the shortest.

Indeed: on the surface of the ball, the shortest distance between two points is the arc of a great circle connecting them. But the circle of parallels - small circle. An arc of a great circle is less curved than an arc of any small circle drawn through the same two points: a larger radius corresponds to a smaller curvature. Pull the thread between our two points on the globe (cf. fig. 3); you will make sure that it does not lie along the parallel at all. A stretched thread is an indisputable indicator of the shortest path, and if it does not coincide with a parallel on a globe, then on a nautical chart the shortest path is not indicated by a straight line either: recall that circles of parallels are depicted on such a map by straight lines, any line that does not coincide with a straight line , there is curve .



Rice. 3. A simple way to find the really shortest path between two points: you need to pull a thread between these points on the globe


After what has been said, it becomes clear why the shortest path on the nautical chart is depicted not by a straight line, but by a curved line.

They say that when choosing a direction for the Nikolaev (now October) railway, there were endless disputes about which way to lay it. The end of the controversy was put by the intervention of Tsar Nicholas I, who solved the problem literally "straightforwardly": he connected Petersburg with Moscow along a line. If this had been done on a mercator map, it would have turned out to be an embarrassing surprise: instead of a straight line, the road would turn out to be a curve.

He who does not avoid calculations can make sure by simple calculation that the path that appears to us on the map as a curve is in fact shorter than the one that we are ready to consider straight. Let our two harbors lie on the 60th parallel and are separated by a distance of 60 °. (Whether such two harbors actually exist is of course irrelevant for the calculation.)



Rice. 4. To the calculation of the distances between points A and B on the ball along the arc of parallel and along the arc of a great circle


In fig. 4 point O - center of the globe, AB - arc of a circle of latitude on which harbors lie A and B; v her 60 °. The center of the circle of latitude is at a point WITH Imagine that from the center O the globe is drawn through the same harbor arc of a great circle: its radius OB = OA = R; it will pass close to the drawn arc AB, but will not coincide with her.

Let's calculate the length of each arc. Since the points A and V lie at a latitude of 60 °, then the radii OA and OV make up with OS(the axis of the globe) an angle of 30 °. In a right triangle ASO leg AC (= r), opposite an angle of 30 °, equal to half the hypotenuse JSC;

means, r = R / 2 Arc length AB is one-sixth of the length of the circle of latitude, and since this circle is half the length of the large circle (correspondingly half the radius), the length of the arc of the small circle



To determine now the length of the arc of a large circle drawn between the same points (i.e., the shortest path between them), you need to know the value of the angle AOB. Chord AS that contracts an arc of 60 ° (small circle) is the side of a regular hexagon inscribed in the same small circle; therefore AB = r = R / 2

Having drawn a straight line OD, connecting center O the globe with the middle D chords AB, we get a right triangle ODA, where is the angle D - straight:

DA = 1/2 AB and OA = R.

sinAOD = AD: AO = R / 4: R = 0.25

From here we find (according to the tables):

= 14 ° 28 ", 5

and therefore

= 28 ° 57 ".

Now it is no longer difficult to find the desired length of the shortest path in kilometers. The calculation can be simplified if we remember that the length of a minute of the great circle of the globe is mo

We learn that the path in a circle of latitude, depicted on the sea map by a straight line, is 3333 km, and the path in a large circle - along a curve on the map - 3213 km, that is, 120 km shorter.

Armed with a thread and having a globe at hand, you can easily check the correctness of our drawings and make sure that the arcs of the large circles really run as shown in the drawings. Shown in fig. 1 supposedly the "straight" sea route from Africa to Australia is 6020 miles, and the "curved" - 5450 miles, that is, shorter by 570 miles, or 1050 km. The "direct" air route on the sea map from London to Shanghai cuts the Caspian Sea, while the really shortest route runs north of St. Petersburg. It is clear what role these issues play in saving time and fuel.

If in the era of sailing, time was not always valued - then "time" was not yet considered "money" - then with the advent of steam ships you have to pay for every unnecessarily spent ton of coal. That is why today ships are guided along the really shortest path, often using maps made not in the Mercatorian, but in the so-called "central" projection: on these maps, the arcs of large circles are depicted by straight lines.

Why did the former navigators use such deceptive charts and choose unprofitable paths? It is a mistake to think that in the old days they did not know about this particular feature of nautical charts. The reason, of course, is not this, but the fact that the maps drawn according to the method of Mercator have, along with inconveniences, benefits that are very valuable for sailors. Such a map, firstly, depicts individual small parts of the earth's surface without distortion, while maintaining the corners of the contour. This is not contradicted by the fact that with distance from the equator, all contours noticeably stretch. At high latitudes, the stretching is so significant that the nautical chart inspires a person unfamiliar with its features, a completely false idea of ​​the true size of the continents: Greenland seems to be the same size as Africa, Alaska is larger than Australia, although Greenland is 15 times smaller than Africa, and Alaska is together with Greenland half the size of Australia. But the sailor, who is well acquainted with these features of the card, cannot be misled. He reconciles with them, especially since within small areas the sea map gives an exact likeness of nature (Fig. 5).

But the nautical chart greatly facilitates the solution of the tasks of navigational practice. This is the only kind of charts in which the path of a ship on a constant course is represented by a straight line. To go "constant course" means to keep invariably in one direction, one definite "rumba", in other words, to go so as to cross all meridians at an equal angle. But this path ("loxodrome") can be represented as a straight line only on a map on which all meridians are straight lines parallel to each other. And since on the globe the circles of latitude intersect with the meridians at right angles, then on such a map the circles of latitude should be straight lines perpendicular to the lines of the meridians. In short, we come to precisely that coordinate grid, which is the characteristic feature of the nautical chart.




Rice. 5. Marine or mercator map of the globe. On such maps, the dimensions of the contours far from the equator are greatly exaggerated. Which, for example, is bigger: Greenland or Australia? (Answer in text)


Mariners' predilection for Mercator cards is now clear. Wanting to determine the course to be held while going to the designated port, the navigator applies a ruler to the endpoints of the path and measures the angle it makes with the meridians. Keeping on the open sea all the time in this direction, the navigator will accurately bring the ship to the target. You see that the “loxodrome” is not the shortest and most economical, but in a certain respect it is a very convenient route for the sailor. To reach, for example, from the Cape of Good Hope to the southern tip of Australia (see Fig. 1), one must invariably keep the same course S 87 °, 50 ". "), It is necessary, as can be seen from the figure, to continuously change the course of the vessel: start from the course S 42 °, 50", and end with the course N 53 °, 50 "(in this case, the shortest route is even impracticable - it rests against the ice wall of Antarctica ).

Both paths - along the "loxodrome" and along the "orthodrome" - coincide only when the path along a large circle is depicted on the sea map by a straight line: when moving along the equator or along the meridian. In all other cases, these paths are different.

The path along the dotted line in the picture is shorter than the path along the solid line. And now in a little more detail on the example of sea routes:

If you sail at a constant heading, then the trajectory of the ship's movement on the earth's surface will be a curve, called in mathematics logarithmicspiral.

In navigation, this complex double curvature line is called loxodromia, which in translation from Greek means "oblique run".

However, the shortest distance between two points on the globe is measured along the arc of a great circle.

The great-circle arc is obtained as a trace from the intersection of the earth's surface with a plane passing through the center of the earth, taken as a ball.

In navigation, the great circle is called orthodromy, which in translation means "straight run". The second feature of the orthodromy is that it crosses the meridians at different angles (Fig. 29).

The difference in the distances between two points on the earth's surface of the poloksodrome and orthodrome is of practical importance only for large ocean crossings.

Under normal conditions, this difference is neglected and swimming is performed on a constant course, i.e. along the loxodrome.

To derive the equation, we take on the loxodrome (Fig. 30, a) two points A and V, the distance between which is elementarily small. Drawing meridians and a parallel through them, we get an elementary right-angled spherical triangle ABC. In this triangle, the angle formed by the intersection of the meridian and the parallel is right, and the angle PnAB equal to the heading of the vessel K. Cathet AS represents a segment of the meridian arc and can be expressed

where R - radius of the Earth, taken for a ball;

Δφ - elementary latitude increment (latitude difference).

Cathetus SV represents a parallel arc segment

where r - parallel radius;

Δλ - elementary difference in longitudes.

From triangular OO 1 C you can find that

Then in the final form of the legs SV can be expressed like this:

Taking an elementary spherical triangle ABC for flat, write

After the cut R and replacing elementarily small increments of coordinates by infinitesimal we will have

Let us integrate the resulting expression within the range from φ 1, λ 1 to φ 2, λ 2 assuming the tgK value to be a constant:

On the right, we have a tabular integral. After substituting its value, we obtain the loxodromy equation on the ball

Analysis of this equation leads to the following conclusions:

At courses 0 and 180 °, the loxodrome turns into an arc of a great circle - the meridian;

At the courses of 90 and 270 °, the loxodrome coincides with the parallel;

The loxodromia crosses each parallel only once, and each meridian - countless times. those. spirally approaching the pole, it does not reach it.

Sailing on a constant course, that is, on a loxodrome, although it is not the shortest distance between two points on the Earth, is a significant convenience for the navigator.

The requirements for a nautical navigational chart can be formulated based on the advantage of sailing along the loxodrome and the results of the analysis of its equation as follows.

1. Loxodromia, crossing the meridians at a constant angle, should be depicted as a straight line.

2. The cartographic projection used for the construction of maps must be conformal so that the courses, bearings and angles on it correspond to their values ​​on the ground.

3. Meridians and parallels, like course lines 0, 90, 180 ° and 270 °, must be mutually perpendicular straight lines.

The shortest distance between two given points on the Earth's surface, taken as a ball, is the smaller of the arcs of the great circle passing through these points. In addition to the case of a ship following the meridian or equator, the orthodrome crosses the meridians at different angles. Therefore, a vessel following such a curve must always change its course. In practice, it is more convenient to follow a course that makes a constant angle with the meridians and is depicted on the map in the Mercator projection as a straight line - loxodromy. However, at large distances, the difference in the length of the orthodrome and loxodrome reaches a significant value. Therefore, in such cases, the orthodrome is calculated and intermediate points are marked on it, between which the loxodrome is swimming.

A cartographic projection that satisfies the listed requirements was proposed by the Dutch cartographer Gerard Kramer (Mercator) in 1569. In honor of its creator, the projection was named mercatorial.

And who wants to get even more interesting information, find out more The original article is on the site InfoGlaz.rf The link to the article this copy was made from is

(Descriptive geometry)
  • CD (CXDX, C2D2) depicted as a point C5 = D5 А5В5 equals...
    (Descriptive geometry)
  • Determining the distance between two parallel planes
    Determination of the distance between two parallel planes in general position 01 | X it is convenient to reduce it to the task of determining the distance between the same two planes, transformed into the position of the projectors. In this case, the distance between the planes is defined as the perpendicular between the straight lines, ...
    (Descriptive geometry)
  • Determining the distance between two crossed lines
    If you want to determine the shortest distance between two crossing lines, you have to change the systems of projection planes twice. When solving this problem, the straight line CD (CXDX, C2D2) depicted as a point C5 = D5(fig. 198). Distance from this point to projection А5В5 equals...
    (Descriptive geometry)
  • The angle between two crossed straight lines
    This is the angle between two intersecting lines parallel to the data. Thus, this task is similar to the previous one. To solve it, you need to take an arbitrary point and draw two straight lines through it, parallel to the given intersecting straight lines, and using the transformation of projections, determine the desired angle ...
    (Fundamentals of descriptive geometry. A short course and a collection of problems.)
  • Determining the distance between two parallel lines
    The problem is solved by a double replacement of projection planes. At the final stage, one of the projection planes must be perpendicular to one of the crossing lines. Then the shortest distance between them is determined by the size of the perpendicular segment to another intersecting straight line (Fig. 199) ....
    (Descriptive geometry)
  • Dijkstra’s algorithm is a graph algorithm invented by the Dutch scientist Edsger Dijkstra in 1959. Finds the shortest paths from one of the vertices of the graph to all the others. The algorithm works only for graphs without edges of negative weight.

    Let's consider the execution of the algorithm using the example of the graph shown in the figure.

    Let it be required to find the shortest distances from the 1st vertex to all the others.

    The circles indicate the vertices, the lines - the paths between them (the edges of the graph). The numbers of the vertices are indicated in circles, their "price" is indicated above the edges - the length of the path. Next to each vertex, a red label is indicated - the length of the shortest path to this vertex from vertex 1.

    First step... Let's consider a step of Dijkstra's algorithm for our example. The vertex 1 has the minimum label. Its neighbors are vertices 2, 3 and 6.

    The first neighbor in turn of vertex 1 is vertex 2, because the path length to it is minimal. The length of the path to it through vertex 1 is equal to the sum of the value of the label of vertex 1 and the length of the edge going from the 1st to the 2nd, that is, 0 + 7 = 7. This is less than the current label of vertex 2, infinity, so the new label of the 2nd vertices is 7.

    We perform a similar operation with two other neighbors of the 1st vertex - the 3rd and 6th.

    All neighbors of vertex 1 are checked. The current minimum distance to peak 1 is considered final and is not subject to revision (the fact that this is really so was first proved by E. Dijkstra). Let's delete it from the graph to mark that this vertex has been visited.

    Second step... The algorithm step is repeated. Find the “closest” of the unvisited vertices again. This is vertex 2, labeled 7.

    We again try to decrease the labels of the neighbors of the selected vertex, trying to pass through the 2nd vertex into them. The neighbors of vertex 2 are vertices 1, 3, and 4.

    The first (in order) neighbor of vertex 2 is vertex 1. But it has already been visited, so we do nothing with the 1st vertex.

    The next neighbor of vertex 2 is vertex 3, since it has the minimum label of the vertices marked as not visited. If you go to it through 2, then the length of such a path will be equal to 17 (7 + 10 = 17). But the current label of the third vertex is 9, which is less than 17, so the label does not change.

    Another neighbor of vertex 2 is vertex 4. If you go to it through the 2nd, then the length of such a path will be equal to the sum of the shortest distance to the 2nd vertex and the distance between vertices 2 and 4, that is, 22 (7 + 15 = 22) ... Since 22<, устанавливаем метку вершины 4 равной 22.

    All neighbors of vertex 2 have been viewed, freeze the distance to it and mark it as visited.

    Third step... We repeat the step of the algorithm, selecting vertex 3. After its "processing", we get the following results:

    Further steps... We repeat the step of the algorithm for the remaining vertices. These will be vertices 6, 4, and 5, respectively.

    Completion of Algorithm Execution... The algorithm terminates when no more vertices can be processed. In this example, all the vertices are crossed out, but it is a mistake to believe that this will be so in any example - some vertices may remain uncrossed if they cannot be reached, that is, if the graph is disconnected. The result of the algorithm can be seen in the last figure: the shortest path from top 1 to 2 is 7, to 3 is 9, to 4 is 20, to 5 is 20, to 6 is 11.

    Implementation of the algorithm in various programming languages:

    C ++

    #include "stdafx.h" #include using namespace std; const int V = 6; // Dijkstra's algorithm void Dijkstra (int GR [V] [V], int st) (int distance [V], count, index, i, u, m = st + 1; bool visited [V]; for (i = 0; i "< "<> "; cin >> start; Dijkstra (GR, start-1); system (" pause >> void ");)

    Pascal

    program DijkstraAlgorithm; uses crt; const V = 6; inf = 100000; type vektor = array of integer; var start: integer; const GR: array of integer = ((0, 1, 4, 0, 2, 0), (0, 0, 0, 9, 0, 0), (4, 0, 0, 7, 0, 0), (0, 9, 7, 0, 0, 2), (0, 0, 0, 0, 0, 8), (0, 0, 0, 0, 0, 0)); (Dijkstra's algorithm) procedure Dijkstra (GR: array of integer; st: integer); var count, index, i, u, m, min: integer; distance: vektor; visited: array of boolean; begin m: = st; for i: = 1 to V do begin distance [i]: = inf; visited [i]: = false; end; distance: = 0; for count: = 1 to V-1 do begin min: = inf; for i: = 1 to V do if (not visited [i]) and (distance [i]<=min) then begin min:=distance[i]; index:=i; end; u:=index; visited[u]:=true; for i:=1 to V do if (not visited[i]) and (GR<>0) and (distance [u]<>inf) and (distance [u] + GR inf then writeln (m, ">", i, "=", distance [i]) else writeln (m, ">", i, "=", "route not available"); end; (main program block) begin clrscr; write ("Start vertex >>"); read (start); Dijkstra (GR, start); end.

    Java

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.StringTokenizer; public class Solution (private static int INF = Integer.MAX_VALUE / 2; private int n; // the number of vertices in the digraph private int m; // the number of arcs in the digraph private ArrayList adj; // adjacency list private ArrayList weight; // weight of the edge in the digraph private boolean used; // array for storing information about passed and not passed vertices private int dist; // array for storing the distance from the starting vertex // array of ancestors needed to restore the shortest path from the starting vertex private int pred; int start; // starting vertex, from which the distance to all others is sought private BufferedReader cin; private PrintWriter cout; private StringTokenizer tokenizer; // procedure for starting Dijkstra's algorithm from the starting vertex private void dejkstra (int s) (dist [s] = 0; // the shortest distance to the starting vertex is 0 for (int iter = 0; iter< n; ++iter) { int v = -1; int distV = INF; //выбираем вершину, кратчайшее расстояние до которого еще не найдено for (int i = 0; i < n; ++i) { if (used[i]) { continue; } if (distV < dist[i]) { continue; } v = i; distV = dist[i]; } //рассматриваем все дуги, исходящие из найденной вершины for (int i = 0; i < adj[v].size(); ++i) { int u = adj[v].get(i); int weightU = weight[v].get(i); //релаксация вершины if (dist[v] + weightU < dist[u]) { dist[u] = dist[v] + weightU; pred[u] = v; } } //помечаем вершину v просмотренной, до нее найдено кратчайшее расстояние used[v] = true; } } //процедура считывания входных данных с консоли private void readData() throws IOException { cin = new BufferedReader(new InputStreamReader(System.in)); cout = new PrintWriter(System.out); tokenizer = new StringTokenizer(cin.readLine()); n = Integer.parseInt(tokenizer.nextToken()); //считываем количество вершин графа m = Integer.parseInt(tokenizer.nextToken()); //считываем количество ребер графа start = Integer.parseInt(tokenizer.nextToken()) - 1; //инициализируем списка смежности графа размерности n adj = new ArrayList[n]; for (int i = 0; i < n; ++i) { adj[i] = new ArrayList(); ) // initialization of the list, which stores the weights of the edges weight = new ArrayList [n]; for (int i = 0; i< n; ++i) { weight[i] = new ArrayList(); ) // read the graph specified by the list of edges for (int i = 0; i< m; ++i) { tokenizer = new StringTokenizer(cin.readLine()); int u = Integer.parseInt(tokenizer.nextToken()); int v = Integer.parseInt(tokenizer.nextToken()); int w = Integer.parseInt(tokenizer.nextToken()); u--; v--; adj[u].add(v); weight[u].add(w); } used = new boolean[n]; Arrays.fill(used, false); pred = new int[n]; Arrays.fill(pred, -1); dist = new int[n]; Arrays.fill(dist, INF); } //процедура восстановления кратчайшего пути по массиву предком void printWay(int v) { if (v == -1) { return; } printWay(pred[v]); cout.print((v + 1) + " "); } //процедура вывода данных в консоль private void printData() throws IOException { for (int v = 0; v < n; ++v) { if (dist[v] != INF) { cout.print(dist[v] + " "); } else { cout.print("-1 "); } } cout.println(); for (int v = 0; v < n; ++v) { cout.print((v + 1) + ": "); if (dist[v] != INF) { printWay(v); } cout.println(); } cin.close(); cout.close(); } private void run() throws IOException { readData(); dejkstra(start); printData(); cin.close(); cout.close(); } public static void main(String args) throws IOException { Solution solution = new Solution(); solution.run(); } }

    Another option:

    Import java.io. *; import java.util. *; public class Dijkstra (private static final Graph.Edge GRAPH = (new Graph.Edge ("a", "b", 7), new Graph.Edge ("a", "c", 9), new Graph.Edge ( "a", "f", 14), new Graph.Edge ("b", "c", 10), new Graph.Edge ("b", "d", 15), new Graph.Edge ("c "," d ", 11), new Graph.Edge (" c "," f ", 2), new Graph.Edge (" d "," e ", 6), new Graph.Edge (" e ", "f", 9),); private static final String START = "a"; private static final String END = "e"; public static void main (String args) (Graph g = new Graph (GRAPH); g.dijkstra (START); g.printPath (END); //g.printAllPaths ();)) class Graph (private final Map graph; // mapping of vertex names to Vertex objects, built from a set of Edges / ** One edge of the graph (only used by Graph constructor) * / public static class Edge (public final String v1, v2; public final int dist; public Edge (String v1, String v2, int dist) (this.v1 = v1; this.v2 = v2; this.dist = dist;)) / ** One vertex of the graph, complete with mappings to neighbouring vertices * / public static class Vertex implements Comparable (public final String name; public int dist = Integer.MAX_VALUE; // MAX_VALUE assumed to be infinity public Vertex previous = null; public final Map neighbors = new HashMap<>(); public Vertex (String name) (this.name = name;) private void printPath () (if (this == this.previous) (System.out.printf ("% s", this.name);) else if ( this.previous == null) (System.out.printf ("% s (unreached)", this.name);) else (this.previous.printPath (); System.out.printf ("->% s ( % d) ", this.name, this.dist);)) public int compareTo (Vertex other) (return Integer.compare (dist, other.dist);)) / ** Builds a graph from a set of edges * / public Graph (Edge edges) (graph = new HashMap<>(edges.length); // one pass to find all vertices for (Edge e: edges) (if (! graph.containsKey (e.v1)) graph.put (e.v1, new Vertex (e.v1)); if (! graph. containsKey (e.v2)) graph.put (e.v2, new Vertex (e.v2));) // another pass to set neighboring vertices for (Edge e: edges) (graph.get (e.v1). neighbors.put (graph.get (e.v2), e.dist); //graph.get(e.v2).neighbors.put(graph.get(e.v1), e.dist); // also do this for an undirected graph)) / ** Runs dijkstra using a specified source vertex * / public void dijkstra (String startName) (if (! graph.containsKey (startName)) (System.err.printf ("Graph doesn" t contain start vertex \ "% s \" \ n ", startName); return;) final Vertex source = graph.get (startName); NavigableSet q = new TreeSet<>(); // set-up vertices for (Vertex v: graph.values ​​()) (v.previous = v == source? source: null; v.dist = v == source? 0: Integer.MAX_VALUE; q.add ( v);) dijkstra (q); ) / ** Implementation of dijkstra "s algorithm using a binary heap. * / Private void dijkstra (final NavigableSet q) (Vertex u, v; while (! q.isEmpty ()) (u = q.pollFirst (); // vertex with shortest distance (first iteration will return source) if (u.dist == Integer.MAX_VALUE) break; // we can ignore u (and any other remaining vertices) since they are unreachable // look at distances to each neighbor for (Map.Entry a: u.neighbors.entrySet ()) (v = a.getKey (); // the neighbor in this iteration final int alternateDist = u.dist + a.getValue (); if (alternateDist< v.dist) { // shorter path to neighbour found q.remove(v); v.dist = alternateDist; v.previous = u; q.add(v); } } } } /** Prints a path from the source to the specified vertex */ public void printPath(String endName) { if (!graph.containsKey(endName)) { System.err.printf("Graph doesn"t contain end vertex \"%s\"\n", endName); return; } graph.get(endName).printPath(); System.out.println(); } /** Prints the path from the source to every vertex (output order is not guaranteed) */ public void printAllPaths() { for (Vertex v: graph.values()) { v.printPath(); System.out.println(); } } }

    C

    #include #include #include // # define BIG_EXAMPLE typedef struct node_t node_t, * heap_t; typedef struct edge_t edge_t; struct edge_t (node_t * nd; / * target of this edge * / edge_t * sibling; / * for singly linked list * / int len; / * edge cost * /); struct node_t (edge_t * edge; / * singly linked list of edges * / node_t * via; / * where previous node is in shortest path * / double dist; / * distance from origining node * / char name; / * the, er , name * / int heap_idx; / * link to heap position for updating distance * /); / * --- edge management --- * / #ifdef BIG_EXAMPLE # define BLOCK_SIZE (1024 * 32 - 1) #else # define BLOCK_SIZE 15 #endif edge_t * edge_root = 0, * e_next = 0; / * Don "t mind the memory management stuff, they are besides the point. Pretend e_next = malloc (sizeof (edge_t)) * / void add_edge (node_t * a, node_t * b, double d) (if (e_next == edge_root ) (edge_root = malloc (sizeof (edge_t) * (BLOCK_SIZE + 1)); edge_root.sibling = e_next; e_next = edge_root + BLOCK_SIZE;) --e_next; e_next-> nd = b; e_next-> len = d; e_next -> sibling = a-> edge; a-> edge = e_next;) void free_edges () (for (; edge_root; edge_root = e_next) (e_next = edge_root.sibling; free (edge_root);)) / * --- priority queue stuff --- * / heap_t * heap; int heap_len; void set_dist (node_t * nd, node_t * via, double d) (int i, j; / * already knew better path * / if (nd-> via && d> = nd-> dist) return; / * find existing heap entry, or create a new one * / nd-> dist = d; nd-> via = via; i = nd-> heap_idx; if (! i) i = ++ heap_len; / * upheap * / for (; i> 1 && nd-> dist< heap->dist; i = j) (heap [i] = heap [j]) -> heap_idx = i; heap [i] = nd; nd-> heap_idx = i; ) node_t * pop_queue () (node_t * nd, * tmp; int i, j; if (! heap_len) return 0; / * remove leading element, pull tail element there and downheap * / nd = heap; tmp = heap; for (i = 1; i< heap_len && (j = i * 2) <= heap_len; i = j) { if (j < heap_len && heap[j]->dist> heap-> dist) j ++; if (heap [j] -> dist> = tmp-> dist) break; (heap [i] = heap [j]) -> heap_idx = i; ) heap [i] = tmp; tmp-> heap_idx = i; return nd; ) / * --- Dijkstra stuff; unreachable nodes will never make into the queue --- * / void calc_all (node_t * start) (node_t * lead; edge_t * e; set_dist (start, start, 0); while ((lead = pop_queue ())) for ( e = lead-> edge; e; e = e-> sibling) set_dist (e-> nd, lead, lead-> dist + e-> len);) void show_path (node_t * nd) (if (nd-> via == nd) printf ("% s", nd-> name); else if (! nd-> via) printf ("% s (unreached)", nd-> name); else (show_path (nd-> via); printf ("->% s (% g)", nd-> name, nd-> dist);)) int main (void) (#ifndef BIG_EXAMPLE int i; # define N_NODES ("f" - " a "+ 1) node_t * nodes = calloc (sizeof (node_t), N_NODES); for (i = 0; i< N_NODES; i++) sprintf(nodes[i].name, "%c", "a" + i); # define E(a, b, c) add_edge(nodes + (a - "a"), nodes + (b - "a"), c) E("a", "b", 7); E("a", "c", 9); E("a", "f", 14); E("b", "c", 10);E("b", "d", 15);E("c", "d", 11); E("c", "f", 2); E("d", "e", 6); E("e", "f", 9); # undef E #else /* BIG_EXAMPLE */ int i, j, c; # define N_NODES 4000 node_t *nodes = calloc(sizeof(node_t), N_NODES); for (i = 0; i < N_NODES; i++) sprintf(nodes[i].name, "%d", i + 1); /* given any pair of nodes, there"s about 50% chance they are not connected; if connected, the cost is randomly chosen between 0 and 49 (inclusive! see output for consequences) */ for (i = 0; i < N_NODES; i++) { for (j = 0; j < N_NODES; j++) { /* majority of runtime is actually spent here */ if (i == j) continue; c = rand() % 100; if (c < 50) continue; add_edge(nodes + i, nodes + j, c - 50); } } #endif heap = calloc(sizeof(heap_t), N_NODES + 1); heap_len = 0; calc_all(nodes); for (i = 0; i < N_NODES; i++) { show_path(nodes + i); putchar("\n"); } #if 0 /* real programmers don"t free memories (they use Fortran) */ free_edges(); free(heap); free(nodes); #endif return 0; }

    PHP

    $ edge, "cost" => $ edge); $ neighbors [$ edge] = array ("end" => $ edge, "cost" => $ edge); ) $ vertices = array_unique ($ vertices); foreach ($ vertices as $ vertex) ($ dist [$ vertex] = INF; $ previous [$ vertex] = NULL;) $ dist [$ source] = 0; $ Q = $ vertices; while (count ($ Q)> 0) (// TODO - Find faster way to get minimum $ min = INF; foreach ($ Q as $ vertex) (if ($ dist [$ vertex]< $min) { $min = $dist[$vertex]; $u = $vertex; } } $Q = array_diff($Q, array($u)); if ($dist[$u] == INF or $u == $target) { break; } if (isset($neighbours[$u])) { foreach ($neighbours[$u] as $arr) { $alt = $dist[$u] + $arr["cost"]; if ($alt < $dist[$arr["end"]]) { $dist[$arr["end"]] = $alt; $previous[$arr["end"]] = $u; } } } } $path = array(); $u = $target; while (isset($previous[$u])) { array_unshift($path, $u); $u = $previous[$u]; } array_unshift($path, $u); return $path; } $graph_array = array(array("a", "b", 7), array("a", "c", 9), array("a", "f", 14), array("b", "c", 10), array("b", "d", 15), array("c", "d", 11), array("c", "f", 2), array("d", "e", 6), array("e", "f", 9)); $path = dijkstra($graph_array, "a", "e"); echo "path is: ".implode(", ", $path)."\n";


    Python

    from collections import namedtuple, queue from pprint import pprint as pp inf = float ("inf") Edge = namedtuple ("Edge", "start, end, cost") class Graph (): def __init __ (self, edges): self .edges = edges2 = self.vertices = set (sum ((for e in edges2),)) def dijkstra (self, source, dest): assert source in self.vertices dist = (vertex: inf for vertex in self.vertices ) previous = (vertex: None for vertex in self.vertices) dist = 0 q = self.vertices.copy () neighbors = (vertex: set () for vertex in self.vertices) for start, end, cost in self. edges: neighbors.add ((end, cost)) #pp (neighbors) while q: u = min (q, key = lambda vertex: dist) q.remove (u) if dist [u] == inf or u = = dest: break for v, cost in neighbors [u]: alt = dist [u] + cost if alt< dist[v]: # Relax (u,v,a) dist[v] = alt previous[v] = u #pp(previous) s, u = deque(), dest while previous[u]: s.pushleft(u) u = previous[u] s.pushleft(u) return s graph = Graph([("a", "b", 7), ("a", "c", 9), ("a", "f", 14), ("b", "c", 10), ("b", "d", 15), ("c", "d", 11), ("c", "f", 2), ("d", "e", 6), ("e", "f", 9)]) pp(graph.dijkstra("a", "e")) Output: ["a", "c", "d", "e"]