How to resolve the algorithm Dijkstra's algorithm step by step in the Pascal programming language
How to resolve the algorithm Dijkstra's algorithm step by step in the Pascal programming language
Table of Contents
Problem Statement
Dijkstra's algorithm, conceived by Dutch computer scientist Edsger Dijkstra in 1956 and published in 1959, is a graph search algorithm that solves the single-source shortest path problem for a graph with non-negative edge path costs, producing a shortest path tree.
This algorithm is often used in routing and as a subroutine in other graph algorithms.
For a given source vertex (node) in the graph, the algorithm finds the path with lowest cost (i.e. the shortest path) between that vertex and every other vertex.
If the vertices of the graph represent cities and edge path costs represent driving distances between pairs of cities connected by a direct road, Dijkstra's algorithm can be used to find the shortest route between one city and all other cities.
As a result, the shortest path first is widely used in network routing protocols, most notably:
The inputs to Dijkstra's algorithm are a directed and weighted graph consisting of 2 or more nodes, generally represented by:
A destination node is not specified. The output is a set of edges depicting the shortest path to each destination node.
You can use numbers or names to identify vertices in your program.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Dijkstra's algorithm step by step in the Pascal programming language
Source code in the pascal programming language
program dijkstra(output);
type
{ We dynamically build the list of vertices from the edge list,
just to avoid repeating ourselves in the graph input. Vertices are linked
together via their `next` pointers to form a list of all vertices (sorted by
name), while the `previous` pointer indicates the previous vertex along the
shortest path to this one. }
vertex = record
name: char;
visited: boolean;
distance: integer;
previous: ^vertex;
next: ^vertex;
end;
vptr = ^vertex;
{ The graph is specified as an array of these }
edge_desc = record
source: char;
dest: char;
weight: integer;
end;
const
{ the input graph }
edges: array of edge_desc = (
(source:'a'; dest:'b'; weight:7),
(source:'a'; dest:'c'; weight:9),
(source:'a'; dest:'f'; weight:14),
(source:'b'; dest:'c'; weight:10),
(source:'b'; dest:'d'; weight:15),
(source:'c'; dest:'d'; weight:11),
(source:'c'; dest:'f'; weight:2),
(source:'d'; dest:'e'; weight:6),
(source:'e'; dest:'f'; weight:9)
);
{ find the shortest path to all nodes starting from this one }
origin: char = 'a';
var
head_vertex: vptr = nil;
curr, next, closest: vptr;
vtx: vptr;
dist: integer;
edge: edge_desc;
done: boolean = false;
{ allocate a new vertex node with the given name and `next` pointer }
function new_vertex(key: char; next: vptr): vptr;
var
vtx: vptr;
begin
new(vtx);
vtx^.name := key;
vtx^.visited := false;
vtx^.distance := maxint;
vtx^.previous := nil;
vtx^.next := next;
new_vertex := vtx;
end;
{ look up a vertex by name; create it if needed }
function find_or_make_vertex(key: char): vptr; var
vtx, prev, found: vptr;
done: boolean;
begin
found := nil;
if head_vertex = nil then
head_vertex := new_vertex(key, nil)
else if head_vertex^.name > key then
head_vertex := new_vertex(key, head_vertex);
if head_vertex^.name = key then
found := head_vertex
else begin
prev := head_vertex;
vtx := head_vertex^.next;
done := false;
while not done do
if vtx = nil then
done := true
else if vtx^.name >= key then
done := true
else begin
prev := vtx;
vtx := vtx^.next
end;
if vtx <> nil then
if vtx^.name = key then
found := vtx;
if found = nil then begin
prev^.next := new_vertex(key, vtx);
found := prev^.next;
end
end;
find_or_make_vertex := found
end;
{ display the path to a vertex indicated by its `previous` pointer chain }
procedure write_path(vtx: vptr);
begin
if vtx <> nil then begin
if vtx^.previous <> nil then begin
write_path(vtx^.previous);
write('→');
end;
write(vtx^.name);
end;
end;
begin
curr := find_or_make_vertex(origin);
curr^.distance := 0;
curr^.previous := nil;
while not done do begin
for edge in edges do begin
if edge.source = curr^.name then begin
next := find_or_make_vertex(edge.dest);
dist := curr^.distance + edge.weight;
if dist < next^.distance then begin
next^.distance := dist;
next^.previous := curr;
end
end
end;
curr^.visited := true;
closest := nil;
vtx := head_vertex;
while vtx <> nil do begin
if not vtx^.visited then
if closest = nil then
closest := vtx
else if vtx^.distance < closest^.distance then
closest := vtx;
vtx := vtx^.next;
end;
if closest = nil then
done := true
else if closest^.distance = maxint then
done := true;
curr := closest;
end;
writeln('Shortest path to each vertex from ', origin, ':');
vtx := head_vertex;
while vtx <> nil do begin
write(vtx^.name, ':', vtx^.distance);
if vtx^.distance > 0 then begin
write(' (');
write_path(vtx);
write(')');
end;
writeln();
vtx := vtx^.next;
end
end.
program Dijkstra_console;
// Demo of Dijkstra's algorithm.
// Free Pascal (Lazarus), console application.
uses SysUtils;
type
TNodeSet = (setA, setB, setC);
TNode = record
NodeSet : TNodeSet;
PrevIndex : integer; // previous node in path leading to this node
PathLength : integer; // total length of path to this node
end;
const
// Rosetta code task
NR_NODES = 6;
START_INDEX = 0;
NODE_NAMES: array [0..NR_NODES - 1] of string = ('a','b','c','d','e','f');
// LENGTHS[j,k] = length of branch j -> k, or -1 if no such branch exists.
LENGTHS : array [0..NR_NODES - 1] of array [0..NR_NODES - 1] of integer
= ((-1, 7, 9,-1,-1,14),
(-1,-1,10,15,-1,-1),
(-1,-1,-1,11,-1, 2),
(-1,-1,-1,-1, 6,-1),
(-1,-1,-1,-1,-1, 9),
(-1,-1,-1,-1,-1,-1));
var
nodes : array [0..NR_NODES - 1] of TNode;
j, j_min, k : integer;
lastToSetA, nrInSetA: integer;
branchLength, trialLength, minLength : integer;
lineOut : string;
begin
// Initialize nodes: all in set C
for j := 0 to NR_NODES - 1 do begin
nodes[j].NodeSet := setC;
// No need to initialize PrevIndex and PathLength, as they are
// not used until a value has been assigned by the algorithm.
end;
// Begin by transferring the start node to set A
nodes[START_INDEX].NodeSet := setA;
nodes[START_INDEX].PathLength := 0;
nrInSetA := 1;
lastToSetA := START_INDEX;
// Transfer nodes to set A one at a time, until all have been transferred
while (nrInSetA < NR_NODES) do begin
// Step 1: Work through branches leading from the node that was most recently
// transferred to set A, and deal with end nodes in set B or set C.
for j := 0 to NR_NODES - 1 do begin
branchLength := LENGTHS[ lastToSetA, j];
if (branchLength >= 0) then begin
// If the end node is in set B, and the path to the end node via lastToSetA
// is shorter than the existing path, then update the path.
if (nodes[j].NodeSet = setB) then begin
trialLength := nodes[lastToSetA].PathLength + branchLength;
if (trialLength < nodes[j].PathLength) then begin
nodes[j].PrevIndex := lastToSetA;
nodes[j].PathLength := trialLength;
end;
end
// If the end node is in set C, transfer it to set B.
else if (nodes[j].NodeSet = setC) then begin
nodes[j].NodeSet := setB;
nodes[j].PrevIndex := lastToSetA;
nodes[j].PathLength := nodes[lastToSetA].PathLength + branchLength;
end;
end;
end;
// Step 2: Find the node in set B with the smallest path length,
// and transfer that node to set A.
// (Note that set B cannot be empty at this point.)
minLength := -1; // just to stop compiler warning "might not have been initialized"
j_min := -1; // index of node with smallest path length; will become >= 0
for j := 0 to NR_NODES - 1 do begin
if (nodes[j].NodeSet = setB) then begin
if (j_min < 0) or (nodes[j].PathLength < minLength) then begin
j_min := j;
minLength := nodes[j].PathLength;
end;
end;
end;
nodes[j_min].NodeSet := setA;
inc( nrInSetA);
lastToSetA := j_min;
end;
// Write result to console
WriteLn( SysUtils.Format( 'Shortest paths from node %s:', [NODE_NAMES[START_INDEX]]));
for j := 0 to NR_NODES - 1 do begin
if (j <> START_INDEX) then begin
k := j;
lineOut := NODE_NAMES[k];
repeat
k := nodes[k].PrevIndex;
lineOut := NODE_NAMES[k] + ' -> ' + lineOut;
until (k = START_INDEX);
lineOut := SysUtils.Format( '%3s: length %3d, ',
[NODE_NAMES[j], nodes[j].PathLength]) + lineOut;
WriteLn( lineOut);
end;
end;
end.
You may also check:How to resolve the algorithm Phrase reversals step by step in the Swift programming language
You may also check:How to resolve the algorithm Arithmetic/Rational step by step in the Elisa programming language
You may also check:How to resolve the algorithm Table creation/Postal addresses step by step in the SQL PL programming language
You may also check:How to resolve the algorithm Topological sort step by step in the Nim programming language
You may also check:How to resolve the algorithm Euler's sum of powers conjecture step by step in the Wren programming language