Task: Dijkstra's algorithm



C#: using static System.Linq.Enumerable;
using static System.String;
using static System.Console;
using System.Collections.Generic;
using System;
using EdgeList = System.Collections.Generic.List<(int node, double weight)>;

public static class Dijkstra
{
    public static void Main() {
        Graph graph = new Graph(6);
        Func<char, int> id = c => c - 'a';
        Func<int , char> name = i => (char)(i + 'a');
        foreach (var (start, end, cost) in new [] {
            ('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),
        }) {
            graph.AddEdge(id(start), id(end), cost);
        }

        var path = graph.FindPath(id('a'));
        for (int d = id('b'); d <= id('f'); d++) {
            WriteLine(Join(" -> ", Path(id('a'), d).Select(p => $"{name(p.node)}({p.distance})").Reverse()));
        }
        
        IEnumerable<(double distance, int node)> Path(int start, int destination) {
            yield return (path[destination].distance, destination);
            for (int i = destination; i != start; i = path[i].prev) {
                yield return (path[path[i].prev].distance, path[i].prev);
            }
        }
    }

}

sealed class Graph
{
    private readonly List<EdgeList> adjacency;

    public Graph(int vertexCount) => adjacency = Range(0, vertexCount).Select(v => new EdgeList()).ToList();

    public int Count => adjacency.Count;
    public bool HasEdge(int s, int e) => adjacency[s].Any(p => p.node == e);
    public bool RemoveEdge(int s, int e) => adjacency[s].RemoveAll(p => p.node == e) > 0;

    public bool AddEdge(int s, int e, double weight) {
        if (HasEdge(s, e)) return false;
        adjacency[s].Add((e, weight));
        return true;
    }

    public (double distance, int prev)[] FindPath(int start) {
        var info = Range(0, adjacency.Count).Select(i => (distance: double.PositiveInfinity, prev: i)).ToArray();
        info[start].distance = 0;
        var visited = new System.Collections.BitArray(adjacency.Count);

        var heap = new Heap<(int node, double distance)>((a, b) => a.distance.CompareTo(b.distance));
        heap.Push((start, 0));
        while (heap.Count > 0) {
            var current = heap.Pop();
            if (visited[current.node]) continue;
            var edges = adjacency[current.node];
            for (int n = 0; n < edges.Count; n++) {
                int v = edges[n].node;
                if (visited[v]) continue;
                double alt = info[current.node].distance + edges[n].weight;
                if (alt < info[v].distance) {
                    info[v] = (alt, current.node);
                    heap.Push((v, alt));
                }
            }
            visited[current.node] = true;
        }
        return info;
    }

}

sealed class Heap<T>
{
    private readonly IComparer<T> comparer;
    private readonly List<T> list = new List<T> { default };

    public Heap() : this(default(IComparer<T>)) { }

    public Heap(IComparer<T> comparer) {
        this.comparer = comparer ?? Comparer<T>.Default;
    }

    public Heap(Comparison<T> comparison) : this(Comparer<T>.Create(comparison)) { }

    public int Count => list.Count - 1;

    public void Push(T element) {
        list.Add(element);
        SiftUp(list.Count - 1);
    }

    public T Pop() {
        T result = list[1];
        list[1] = list[list.Count - 1];
        list.RemoveAt(list.Count - 1);
        SiftDown(1);
        return result;
    }

    private static int Parent(int i) => i / 2;
    private static int Left(int i) => i * 2;
    private static int Right(int i) => i * 2 + 1;

    private void SiftUp(int i) {
        while (i > 1) {
            int parent = Parent(i);
            if (comparer.Compare(list[i], list[parent]) > 0) return;
            (list[parent], list[i]) = (list[i], list[parent]);
            i = parent;
        }
    }

    private void SiftDown(int i) {
        for (int left = Left(i); left < list.Count; left = Left(i)) {
            int smallest = comparer.Compare(list[left], list[i]) <= 0 ? left : i;
            int right = Right(i);
            if (right < list.Count && comparer.Compare(list[right], list[smallest]) <= 0) smallest = right;
            if (smallest == i) return;
            (list[i], list[smallest]) = (list[smallest], list[i]);
            i = smallest;
        }
    }

}






VB: Class Branch
Public from As Node 
Public towards As Node
Public length As Integer 
Public distance As Integer 
Public key As String
Class Node
Public key As String
Public correspondingBranch As Branch
Const INFINITY = 32767
Private Sub Dijkstra(Nodes As Collection, Branches As Collection, P As Node, Optional Q As Node)
    
    
    
    
    
    
    
    
    
    
    
    
    
    Dim a As New Collection 
    
    
    
    Dim b As New Collection 
    
    Dim c As New Collection 
    
    
    
    Dim I As New Collection 
    
    
    Dim II As New Collection 
    
    Dim III As New Collection 
    Dim u As Node, R_ As Node, dist As Integer
    
    
    
    For Each n In Nodes
        c.Add n, n.key
    Next n
    For Each e In Branches
        III.Add e, e.key
    Next e
    a.Add P, P.key
    c.Remove P.key
    Set u = P
    Do
        
        
        
        
        
        
        
        
        For Each r In III
            If r.from Is u Then
                Set R_ = r.towards
                If Belongs(R_, c) Then
                    c.Remove R_.key
                    b.Add R_, R_.key
                    Set R_.correspondingBranch = r
                    If u.correspondingBranch Is Nothing Then
                        R_.correspondingBranch.distance = r.length
                    Else
                        R_.correspondingBranch.distance = u.correspondingBranch.distance + r.length
                    End If
                    III.Remove r.key 
                    II.Add r, r.key
                Else
                    If Belongs(R_, b) Then 
                        If R_.correspondingBranch.distance > u.correspondingBranch.distance + r.length Then
                            II.Remove R_.correspondingBranch.key
                            II.Add r, r.key
                            Set R_.correspondingBranch = r 
                            R_.correspondingBranch.distance = u.correspondingBranch.distance + r.length 
                        End If
                    End If
                End If
            End If
        Next r
        
        
        
        
        
        
        dist = INFINITY
        Set u = Nothing
        For Each n In b
            If dist > n.correspondingBranch.distance Then
                dist = n.correspondingBranch.distance
                Set u = n
            End If
        Next n
        b.Remove u.key
        a.Add u, u.key
        II.Remove u.correspondingBranch.key
        I.Add u.correspondingBranch, u.correspondingBranch.key
    Loop Until IIf(Q Is Nothing, a.Count = Nodes.Count, u Is Q)
    If Not Q Is Nothing Then GetPath Q
End Sub
Private Function Belongs(n As Node, col As Collection) As Boolean
    Dim obj As Node
    On Error GoTo err
        Belongs = True
        Set obj = col(n.key)
        Exit Function
err:
        Belongs = False
End Function
Private Sub GetPath(Target As Node)
    Dim path As String
    If Target.correspondingBranch Is Nothing Then
        path = "no path"
    Else
        path = Target.key
        Set u = Target
        Do While Not u.correspondingBranch Is Nothing
            path = u.correspondingBranch.from.key & " " & path
            Set u = u.correspondingBranch.from
        Loop
        Debug.Print u.key, Target.key, Target.correspondingBranch.distance, path
    End If
End Sub
Public Sub test()
    Dim a As New Node, b As New Node, c As New Node, d As New Node, e As New Node, f As New Node
    Dim ab As New Branch, ac As New Branch, af As New Branch, bc As New Branch, bd As New Branch
    Dim cd As New Branch, cf As New Branch, de As New Branch, ef As New Branch
    Set ab.from = a: Set ab.towards = b: ab.length = 7: ab.key = "ab": ab.distance = INFINITY
    Set ac.from = a: Set ac.towards = c: ac.length = 9: ac.key = "ac": ac.distance = INFINITY
    Set af.from = a: Set af.towards = f: af.length = 14: af.key = "af": af.distance = INFINITY
    Set bc.from = b: Set bc.towards = c: bc.length = 10: bc.key = "bc": bc.distance = INFINITY
    Set bd.from = b: Set bd.towards = d: bd.length = 15: bd.key = "bd": bd.distance = INFINITY
    Set cd.from = c: Set cd.towards = d: cd.length = 11: cd.key = "cd": cd.distance = INFINITY
    Set cf.from = c: Set cf.towards = f: cf.length = 2: cf.key = "cf": cf.distance = INFINITY
    Set de.from = d: Set de.towards = e: de.length = 6: de.key = "de": de.distance = INFINITY
    Set ef.from = e: Set ef.towards = f: ef.length = 9: ef.key = "ef": ef.distance = INFINITY
    a.key = "a"
    b.key = "b"
    c.key = "c"
    d.key = "d"
    e.key = "e"
    f.key = "f"
    Dim testNodes As New Collection
    Dim testBranches As New Collection
    testNodes.Add a, "a"
    testNodes.Add b, "b"
    testNodes.Add c, "c"
    testNodes.Add d, "d"
    testNodes.Add e, "e"
    testNodes.Add f, "f"
    testBranches.Add ab, "ab"
    testBranches.Add ac, "ac"
    testBranches.Add af, "af"
    testBranches.Add bc, "bc"
    testBranches.Add bd, "bd"
    testBranches.Add cd, "cd"
    testBranches.Add cf, "cf"
    testBranches.Add de, "de"
    testBranches.Add ef, "ef"
    Debug.Print "From", "To", "Distance", "Path"
    
    Dijkstra testNodes, testBranches, a, e
    
    Dijkstra testNodes, testBranches, a
    GetPath f
End Sub