Graph Theory Summary - Topological Sorting and Shortest Path Problems (Weightless Shortest Path, Dijkstra Algorithm, Graph with Negative Edge Values)

Keywords: Java less github REST

Definition of graph

A graph G = (V,E) consists of a vertex set V and an edge set E.
Each edge is a pair of points (v,w), where v,w < V, sometimes referred to as an arc.
If the pairs of points are ordered, the graph is called directed, and the directed graph is sometimes called digraph.
Vertices V and W adjacent if and only if (v,w) < E.
Sometimes there is a third component called weight or cost.
For a vertex v, the number of bars of an edge (u,v) is called an indegree.

A path in the graph is a sequence of vertices w1,w2,w3,...wN, so (wi,wi+1) < E, 1<= I < N.
The length of such a path is the number of edges on that path, which is equal to N - 1.
A simple path is one where all the vertices on it are different, but the first and last vertices may be the same.

A cycle in a directed graph is a path that satisfies w1 = wN and has a length of at least 1. If the path is a simple path, then the circle is a simple circle.
If a directed graph has no circle, it is called acyclic.A directed acyclic graph is sometimes referred to as a DAG.

If there is a path from each vertex to every other vertex in an undirected graph, the undirected graph is said to be connected.
Directed graphs of this nature are called strongly connected.
If the graph formed by the direction in which the edges fall off is connected, it is called an underlying graph.
If a directed graph is not connected but is a base graph, it is called weakly connected.
A complete graph is a graph in which there is an edge between each pair of vertices.
dense: The number of E bars in the graph is close to V*V, that is, close to the connection between any two points.
sparse graph: The number of E bars in the graph is much less than V*V.

Representation of a graph

Specific Java implementations of diagrams can Click here to view Or click the link below:
https://github.com/0xZhangKe/Algorithms/tree/master/src/com/zhangke/java/graph/adt
I do this using adjacency tables.

adjacency matrix

A simple way to represent a graph is to use a two-dimensional array called the adjacency matrix representation.
Suitable for dense maps.

Adjacency table

If the graph is sparse, a better representation is to use an adjacency list.

Topological Sorting

Topological ordering is a sort of vertices of a directed acyclic graph that makes VJ appear after vi in the sort if there is a path from vi to vj.
A simple algorithm for topological ordering is to first find any vertex without degrees of entry.Then we show the vertex and remove it from the graph along with its edges.We then apply the same method to the rest of the graph.

public static <T> void sort(ListDGraph<T> graph) {
    Queue<Vertex<T>> queue = new ArrayDeque<>();
    Queue<Vertex<T>> resultQueue = new ArrayDeque<>();
    int size = graph.size();
    int[] indegree = new int[size];//Initiation Array
    for (int i = 0; i < size; i++) {
        List<Edge<Vertex<T>>> edges = graph.get(i).getEdgeList();
        for (Edge<Vertex<T>> item : edges) {
            indegree[graph.get(item.getDest())]++;
        }
    }
    for (int i = 0; i < size; i++) {
        if (indegree[i] == 0) {
            queue.offer(graph.get(i));
        }
    }
    while (!queue.isEmpty()) {
        Vertex<T> vertex = queue.poll();
        resultQueue.offer(vertex);
        List<Edge<Vertex<T>>> edges = vertex.getEdgeList();
        if (edges != null) {
            for (Edge<Vertex<T>> edge : edges) {
                int index = graph.get(edge.getDest());
                indegree[index]--;
                if (indegree[index] <= 0) {
                    queue.offer(edge.getDest());
                }
            }
        }
    }
    while (!resultQueue.isEmpty()) {
        Vertex<T> item = resultQueue.poll();
        System.out.print(item.getValue());
        if (!resultQueue.isEmpty()) {
            System.out.print(" -> ");
        }
    }
}

Shortest path algorithm

Enter a weighting graph where the cost (or value) of traversing the arc, ci, j, is associated with each edge (vi, vj).A path V1 v2...The value of V N is_i=1 N-1, and i+1 is called weighted path length.The un weight path length is simply the number of edges on the path, plus N-1.
To solve the shortest path problem, a configuration table concept is introduced here:

For each vertex, we track three pieces of information.
Know: Indicates whether the vertex is known; or
dv: the distance from the starting point s to that point;
pv: Bookkeeping variable, which enables us to show the actual path.

Then define a method for creating the configuration table:

/**
 * An auxiliary configuration table for finding the shortest path
 *
 * Created by ZhangKe on 2019/3/31.
 */
public class TableEntity<T> {
    static final int INFINITY = Integer.MAX_VALUE;
    boolean know = false;
    int dist = INFINITY;
    T path = null;
    static <T> Map<Vertex<T>, TableEntity<Vertex<T>>> getTable(DGraph<T> graph, Vertex<T> vertex){
        Map<Vertex<T>, TableEntity<Vertex<T>>> table = new HashMap<>();
        for (int i = 0; i < graph.size(); i++) {
            Vertex<T> v = graph.get(i);
            TableEntity<Vertex<T>> entity = new TableEntity<>();
            if (v.equals(vertex)) {
                entity.dist = 0;
            }
            table.put(v, entity);
        }
        return table;
    }
    static <T> void printTable(Map<Vertex<T>, TableEntity<Vertex<T>>> table){
        String divider = "        ";
        System.out.print(String.format("v%sKnown%sDv%sPv", divider, divider, divider));
        System.out.println();
        for (Vertex<T> key : table.keySet()) {
            TableEntity<Vertex<T>> itemTable = table.get(key);
            System.out.print(key.getValue() +
                    divider +
                    itemTable.know +
                    divider +
                    itemTable.dist +
                    divider +
                    (itemTable.path == null ? "null" : itemTable.path.getValue()));
            System.out.println();
        }
    }
}

It is important to note that DGraph and other diagram-related implementation classes can be viewed here or clicked on the link below without further explanation here:
https://github.com/0xZhangKe/Algorithms/tree/master/src/com/zhangke/java/graph/adt

No Rights Shortest Path

Using a vertex s as an input parameter, we want to find the shortest path from s to all other vertices. We are only interested in the number of edges contained in the path, so there is no right on the edge.
Obviously, this is a special case of the weighted shortest path problem because we can assign weight 1 to all edges.
The code implementation is as follows:

public <T> void find(DGraph<T> graph, Vertex<T> s) {
    //Create initial configuration table
    Map<Vertex<T>, TableEntity<Vertex<T>>> table = TableEntity.getTable(graph, s);
    Queue<Vertex<T>> queue = new ArrayDeque<>();
    queue.offer(s);
    while (!queue.isEmpty()) {
        Vertex<T> v = queue.poll();
        TableEntity<Vertex<T>> itemTable = table.get(v);
        itemTable.know = true;
        if (v.getEdgeList() != null) {
            for (Edge<Vertex<T>> edge : v.getEdgeList()) {
                if (edge.getDest() != null) {
                    TableEntity<Vertex<T>> destTable = table.get(edge.getDest());
                    if (destTable.dist == TableEntity.INFINITY) {
                        destTable.dist = itemTable.dist + 1;
                        destTable.path = v;
                        queue.offer(edge.getDest());
                    }
                }
            }
        }
    }
    TableEntity.printTable(table);
}

The above search method became breadth-first search.This method processes vertices hierarchically: the vertices closest to the start point are assigned first, and the vertices farthest are assigned last.This is much like a level-order traversal of trees.

Dijkstra algorithm

The general way to solve the single-source shortest path problem is called the Dijkstra algorithm.This 30-year-old solution is the best example of the greedy algorithm.
The Dijkstra algorithm, like the weightless shortest path algorithm, proceeds in stages. At each stage, the Dijkstra algorithm selects a top v, which has the smallest dv among all unknown vertices, and the algorithm declares that the shortest path from s to V is known.

/**
     * 1.Gets the vertex with the smallest value in the list of unlabeled vertices (since all defaults are MAX_VALUE, so only adjacent nodes are possible, essentially finding the smallest value among adjacent nodes)
     * 2.The adjacent points that traverse the vertex are updated with the current path weight value if the adjacent points are not marked and the value is less than the current path weight value
     * 3.Repeat step 1/2
     */
private static <T> void find(DGraph<T> graph, Vertex<T> vertex) {
    Map<Vertex<T>, TableEntity<Vertex<T>>> table = TableEntity.getTable(graph, vertex);
    for (int i = 1; i < graph.size(); i++) {
        Vertex<T> minVertex = findUnknownMin(table);
        if (minVertex == null) {
            break;
        }
        TableEntity<Vertex<T>> minTable = table.get(minVertex);
        int minDist = minTable.dist;
        minTable.know = true;
        if (minVertex.getEdgeList() != null) {
            for (Edge<Vertex<T>> edge : minVertex.getEdgeList()) {
                if (edge.getDest() != null) {
                    TableEntity<Vertex<T>> edgeTable = table.get(edge.getDest());
                    if (!edgeTable.know &&
                        (minDist + edge.getWeight() < edgeTable.dist)) {
                        edgeTable.dist = minDist + edge.getWeight();
                        edgeTable.path = minVertex;
                    }
                }
            }
        }
    }
    TableEntity.printTable(table);
}
/**
     * Reading a minimum dist vertex from an unknown table
     */
private static <T> Vertex<T> findUnknownMin(Map<Vertex<T>, TableEntity<Vertex<T>>> table) {
    int min = TableEntity.INFINITY;
    Vertex<T> vertex = null;
    for (Vertex<T> key : table.keySet()) {
        TableEntity<Vertex<T>> item = table.get(key);
        if (!item.know && min >= item.dist) {
            min = item.dist;
            vertex = key;
        }
    }
    return vertex;
}

Graph with negative edge values

Combining weighted and weightless algorithms will solve this problem.

private static <T> void find(DGraph<T> graph, Vertex<T> vertex) {
    Map<Vertex<T>, TableEntity<Vertex<T>>> table = TableEntity.getTable(graph, vertex);
    Queue<Vertex<T>> queue = new ArrayDeque<>();
    queue.offer(vertex);
    while (!queue.isEmpty()) {
        Vertex<T> itemVertex = queue.poll();
        TableEntity<Vertex<T>> itemTable = table.get(itemVertex);
        itemTable.know = true;
        if (itemVertex.getEdgeList() != null) {
            for (Edge<Vertex<T>> edge : itemVertex.getEdgeList()) {
                if (edge.getDest() != null) {
                    TableEntity<Vertex<T>> destTable = table.get(edge.getDest());
                    if (itemTable.dist + edge.getWeight() < destTable.dist) {
                        destTable.dist = itemTable.dist + edge.getWeight();
                        destTable.path = itemVertex;
                        if (!queue.contains(edge.getDest())) {
                            queue.offer(edge.getDest());
                        }
                    }
                }
            }
        }
    }
    TableEntity.printTable(table);
}

Note: The above is a summary of the learning of graph theory algorithms from mark Allen Weiss.

Posted by drepster on Sun, 28 Apr 2019 18:20:36 -0700