Topological ordering, critical path and shortest path algorithm of graphs--C + + implementation

Source: Internet
Author: User
Tags in degrees

One: Topology sequencing

The topological ordering of a directed acyclic graph (Directed acyclic graph called dag) G is to arrange all the vertices in G into a linear sequence so that any pair of vertices in the graph, U and V, if the Edge (u,v) ∈e (g), the U appears before v in a linear sequence. Typically, such a linear sequence is called a sequence that satisfies the topological order (topological order), referred to as a topological sequence.

Topological ordering is to find the vertex with a degree of 0, and then press the stack in turn. First, the top vertex of the stack is output, and the vertices with this vertex as the end of the arc are removed, and the other vertices are updated in degrees. If the in degree is 0, continue to press the stack. The update is complete to continue out of the stack until the stack is empty. The order of the elements out of the stack and output is the topological sort result. We use arrays to simulate a stack space in our code. : The resulting topological ordering of the graph is: F A D C E B. The algorithm is as follows:
Template <typename T, typename e>void graph_mtx<t, E>::topological_sort () {int num = this->get_  Numvertices (); assert (num! =-1); int *count = new Int[num];assert (count! = nullptr); for (int i=0; i<num; ++i) for (int j=0; j<num; ++J) {if (edge[i][j]! = 0 && edge[i][j]! = Max_cost) count[j]++;//statistics in degrees}int top = -1;for (int i=0; i<num; ++i) if (cou     Nt[i] = = 0) {//using array simulation stack count[i] = top;            Equivalent to the stack, before storage position top = i;   Stores the current position}for (int i=0; i<num; ++i) {if (top = =-1)//If 1, indicating a ring exists, returning to the starting position return; int index_tmp = Top;top = Count[top];   Take stack top elements cout << get_vertex_symbol (index_tmp) << ""; Output stack top element int neighbor_index = Get_firstneighbor (Get_vertex_symbol (index_tmp)); while (neighbor_index! =-1) {if (--c Ount[neighbor_index] = = 0) {//If the entry is reduced to 0, into the stack count[neighbor_index] = Top;top = Neighbor_index;} Neighbor_index = Get_nextneighbor (Get_vertex_symbol (index_tmp), Get_vertex_symbol (Neighbor_index));}} delete []count;}
Two: Critical path critical path: The path length from the source point to the sink point is the longest route called the critical path. A (1..N) in the figure represents the time spent between two activities. : The key path in the figure is a B e G I or a b e H i. Two important concepts: 1. The earliest start time    E, the time spent from a to E is 7 and 5 on the two path, so when does E activity start? There is no doubt that because the E activity began to exist in B, C time two premise, so in the case of the project start time, a to E at least takes time depends on the longer branch of Abe, if the branch is not completed, then C can only wait for another branch to complete, this time e cannot start. Thus, the earliest start time is the time taken from the source point to the longest path of the target vertex. 2. Latest start time    Similarly, the latest start time is calculated backwards from the meeting point. As is the case above, the latest start time depends on the longest branch of the path that passes backwards. The vertices of the first start time and the late start time are the key path vertices, as the graph is easy to know. The algorithm is as follows:
Template <typename T, typename e>void graph_mtx<t, E>::critical_path (const t& vert) {int num = This->ge   T_numvertices (); int *early_start = new Int[num];    Earliest start time array int *late_start = new Int[num]; The latest start time array assert (Early_start! = nullptr && Late_start! = nullptr); int index = Get_vertex_index (vert); Assert (      Index! =-1); for (int i=0; i<num; ++i) early_start[i] = 0; Initialized to 0for (int i=0; i<num; ++i) {int neighbor_index = Get_firstneighbor (Get_vertex_symbol (i)); while (Neighbor_index ! =-1) {int weight = edge[i][neighbor_index];if (Early_start[i]+weight > Early_start[neighbor_index])// If the earliest start time of a point plus the weight of a point to its adjacency point is greater than the value before the adjacency point, the new path is long, update the adjacency point weight early_start[neighbor_index] = Early_start[i]+weight;neighbor_ index = Get_nextneighbor (Get_vertex_symbol (i), Get_vertex_symbol (Neighbor_index));}}   for (int i=0; i<num; ++i) cout << early_start[i] << "";   Print earliest start time cout << endl;for (int i=0; i<num; ++i) late_start[i] = Max_cost; Initialize to infinite time late_start[num-1] = early_start[num-1]; The earliest start time of the meeting point is the same as the latest start time for (int i=num-2; i>=0;-i) {//Except meeting point, starting with num-2 int neighbor_index = Get_firstneighbor (get_vertex_  Symbol (i)); while (neighbor_index! =-1) {int weight = Edge[i][neighbor_index]; if (Late_start[neighbor_index]-weight < late_start[i])//The late start time of the adjacency point of a point minus the last start time before a certain point, indicating that the existing path is long from the backward forward, Update to the latest start time late_start[i] = Late_start[neighbor_index]-weight;neighbor_index = Get_nextneighbor (Get_vertex_symbol (i) , Get_vertex_symbol (Neighbor_index));}}  for (int i=0; i<num; ++i) cout << late_start[i] << ""; Print latest start time cout << endl;for (int i=0; i<num; ++i) if (early_start[i] = = Late_start[i]) cout << get_vertex_  Symbol (i) << ""; If the earliest start time and the latest start time are equal, the critical path is delete []early_start;delete []late_start;}
Three: Shortest path (Dijkstra algorithm) The shortest path problem is a classical algorithm problem in graph theory research, which aims to find the shortest path between two nodes in graph (composed of nodes and paths). The Dijkstra algorithm uses a dist[] array to store the cost of reaching a point, corresponding to its subscript, and a path[] array to store the subscript of a vertex that passes before it reaches that point. Where the lable_incorporated[] array is used to mark vertices that have been incorporated into the path. : The shortest path to the graph is a D C E. The code is as follows:
Template <typename T, typename e>void graph_mtx<t, E>::shortest_path (const t& vert) {int num = This->ge T_numvertices (); int *dist = new Int[num];int *path = new Int[num];int *lable_incorporated = new Int[num];assert (dist! = Nu Llptr && Path! = nullptr && lable_incorporated! = nullptr); int index = Get_vertex_index (vert); assert (in Dex! =-1); for (int i=0; i<num; ++i) {lable_incorporated[i] = false;dist[i] = edge[index][i];if (edge[index][i]! = 0 &   & Dist[i] < max_cost) Path[i] = index;      If the point can be reached from vert, the path defaults to Vert, indicating that the previous vertex to the point is vertelsepath[i] =-1;  Self and unreachable set to -1}lable_incorporated[index] = true; First, the starting point Vert is merged into for (int i=0; i<num-1; ++i) {int min = max_cost;int Min_index = -1;for (int j=0; j<num; ++j) {if (!lable_in CORPORATED[J] && Dist[j] < min) {//Find the least expensive vertex in the non-consolidated vertex min = Dist[j];min_index = j;}}    Lable_incorporated[min_index] = true; Merge this vertex for (int j=0; j<num; ++j) {int weight = edge[min_index][j];if (!lable_incorporated[j] && Weight < max_cost//Note here, if you do not add weight<max_cost, then dist[] array of heavy elements plus max_cost data overflow, the compiler defaults to assignment, which leads to Dist[min _index]+weight always less than dist[j], error && dist[min_index]+weight < dist[j]) {//weight<max_costdist[j] = dist[    Min_index]+weight; Update path PATH[J] = Min_index;}}} cout << "Dist:" << ""; for (int i=0; i<num;  ++i) cout << setw (3) << dist[i] << ""; cout <<endl;cout << "path:" << ""; for (int i=0; i<num; ++i) cout << setw (3) << path[i] << "";d elete []dist;delete []path;}
Four: All code and test common header file:
#ifndef _graph_h#define _graph_h#include <iostream> #include <string.h> #include <assert.h> #include <queue> #include <iomanip>using namespace::std, #define Max_cost 0x7fffffff///////////////////////////// General graph Structure Template <typename T, TypeName E>class    Graph{public:bool is_empty () const;bool is_full () const;int get_numvertices () const;       Current vertex number int get_numedges () const;            Current number of sides public:virtual bool Insert_vertex (const t&) = 0;    Insert vertex virtual bool Insert_edge (const t&, const t&, E) = 0;    Insert Edge Virtual int Get_firstneighbor (const t&) const = 0;    Gets the first adjacency vertex of the virtual int get_nextneighbor (const t&, const t&) const = 0;     Next adjacency vertex of an adjacency vertex virtual void print_graph () const = 0;virtual int Get_vertex_index (const t&) const = 0;         Gets the vertex ordinal protected:static const int vertices_default_size = 10; Default graph vertex number int max_vertices;int num_vertices;int num_edges;}; Template <TypeName T, TypeName E>bool graph<t, E>::is_empty () const{return num_edges = = 0;}  Template <typename T, typename E>bool graph<t, E>::is_full () const{return num_vertices >= max_vertices | |    Num_edges >= max_vertices* (max_vertices-1)/2; Full, divided into vertex full and full}template <typename T, TypeName E>int graph<t, E>::get_numvertices () Const{return num_ vertices;} Template <typename T, typename E>int graph<t, E>::get_numedges () Const{return num_edges;} #define Vertices_ Default_size graph<t, E>::vertices_default_size#define num_vertices graph<t, E>::num_vertices #defi         Ne num_edges graph<t, e>::num_edges#define max_vertices graph<t, e>::max_vertices #endif/*graph.h*/
Implementation file:
#pragma once#include "graph.h"//graph of adjacency matrix notation template <typename T, typename E>class graph_mtx:public graph<t, E&gt ;                   {public:graph_mtx (int);                             ~GRAPH_MTX ();  Public:bool Insert_vertex (const t&); bool Insert_edge (const t&, const t&; E); int Get_firstneighbor (const t&) const;int Get_nextneighbor (const t&, const t&) const;int Get_vertex_index ( const t&) const; t& get_vertex_symbol (const int) const;void print_graph () const;void topological_sort (); void Shortest_path (const T                        &), void Critical_path (const t&);p rivate:t* vertices_list;                              Vertex linear table E **edge; Internal Matrix};template <typename T, TypeName e>graph_mtx<t, e>::graph_mtx (int sz = vertices_default_size) {Max_ vertices = SZ > vertices_default_size?                    Sz:vertices_default_size;vertices_list = new T[max_vertices];edge = new Int*[max_vertices]; Dynamic application of a two-dimensional array for (int i=0; i<max_vertices; ++i) {Edge[i] = new int[max_vertices];}  for (int i=0, i<max_vertices; ++i) for (int j=0; j<max_vertices; ++j) {if (i! = j) Edge[i][j] = max_cost;elseedge[i][j] = 0;} num_vertices = 0;num_edges = 0;} Template <typename T, TypeName E>graph_mtx<t, E>::~graph_mtx () {for (int i=0; i<max_vertices; ++i) Delete [                     ]edge[i]; Separate destruction, and then the total destruction of the delete edge;delete []vertices_list;} Template <typename T, typename E>bool graph_mtx<t, E>::insert_vertex (const t& vert) {if (this->is_ Full ())//derived class function call parent class function, with this or add scope return false;vertices_list[num_vertices++] = Vert;return true;} Template <typename T, typename E>bool graph_mtx<t, E>::insert_edge (const t& vert1, const t& VERT2, E C   OST = Max_cost) {if (This->is_full ())//full return False;int INDEX_V1 = Get_vertex_index (VERT1);  Get the vertex ordinal int index_v2 = Get_vertex_index (VERT2); if (index_v1 = =-1 | | index_v2 =-1) return FALSE;EDGE[INDEX_V1][INDEX_V2]    = Cost; No map + +Num_edges;return true;} Template <typename T, typename E>int graph_mtx<t, E>::get_firstneighbor (const t& vert) Const{int index = g Et_vertex_index (vert); if (Index! =-1) {for (int i=0; i<num_vertices; ++i) {if (edge[index][i]! = 0 && Edge[index ][i] = max_cost) return i;}} return-1;} Template <typename T, typename E>int graph_mtx<t, E>::get_nextneighbor (const t& vert1, const t& VERT2 ) Const{int INDEX_V1 = Get_vertex_index (vert1); int index_v2 = Get_vertex_index (VERT2); if (index_v1! =-1 && index_ V2! =-1) {for (int i=index_v2+1; i<num_vertices; ++i) {if (edge[index_v1][i]! = 0 && edge[index_v1][i]! = Max_cos T) return i;}} return-1;} Template <typename T, typename E>int graph_mtx<t, E>::get_vertex_index (const t& vert) const{for (int i=0; i<num_vertices; ++i) {if (vertices_list[i] = = vert) return i;} return-1;} Template <typename T, typename e>t& graph_mtx<t, e>::get_vertex_symbol (const int index) Const{assert ( IndEx >= 0 && index < this->get_numvertices ()); return vertices_list[index];} Template <typename T, typename e>void graph_mtx<t, E>::p rint_graph () const{if (This->is_empty ()) {cout                      << "Nil graph" << Endl; Null output Nilreturn;} for (int i=0; i<num_vertices; ++i) {cout << vertices_list[i] << "";} cout << endl;for (int i=0; i<num_vertices; ++i) {for (int j=0; j<num_vertices; ++j) {if (edge[i][j]! = max_cost) cout << Edge[i][j] << ""; elsecout << ' @ ' << ' ";} cout << Vertices_list[i] << Endl;}} Template <typename T, typename e>void graph_mtx<t, E>::topological_sort () {int num = this->get_  Numvertices (); assert (num! =-1); int *count = new Int[num];assert (count! = nullptr); for (int i=0; i<num; ++i) for (int j=0; j<num; ++J) {if (edge[i][j]! = 0 && edge[i][j]! = max_cost) count[j]++;} int top = -1;for (int i=0; i<num; ++i) if (count[i] = = 0) {Count[i] = Top;top = i;} FoR (int i=0; i<num; ++i) {if (top = =-1) return; int index_tmp = Top;top = Count[top];cout << Get_vertex_symbol (index_ TMP) << ""; int neighbor_index = Get_firstneighbor (Get_vertex_symbol (index_tmp)); while (neighbor_index! =-1) {if ( --count[neighbor_index] = = 0) {Count[neighbor_index] = Top;top = Neighbor_index;} Neighbor_index = Get_nextneighbor (Get_vertex_symbol (index_tmp), Get_vertex_symbol (Neighbor_index));}} delete []count;} Template <typename T, typename e>void graph_mtx<t, E>::shortest_path (const t& vert) {int num = This->ge T_numvertices (); int *dist = new Int[num];int *path = new Int[num];int *lable_incorporated = new Int[num];assert (dist! = Nu Llptr && Path! = nullptr && lable_incorporated! = nullptr); int index = Get_vertex_index (vert); assert (in Dex! =-1); for (int i=0; i<num; ++i) {lable_incorporated[i] = false;dist[i] = edge[index][i];if (edge[index][i]! = 0 & & Dist[i] < max_cost) Path[i] = index;elsepath[i] =-1;} Lable_incorpOrated[index] = true;for (int i=0; i<num-1; ++i) {int min = max_cost;int Min_index = -1;for (int j=0; j<num; ++j) {if (!l ABLE_INCORPORATED[J] && Dist[j] < min) {min = Dist[j];min_index = j;}} Lable_incorporated[min_index] = true;for (int j=0; j<num; ++j) {int weight = edge[min_index][j];if (!lable_ INCORPORATED[J] && Weight < max_cost && Dist[min_index]+weight < dist[j]) {//WEIGHT&LT;MAX_COSTD IST[J] = dist[min_index]+weight;path[j] = Min_index;}}} cout << "Dist:" << ""; for (int i=0; i<num;  ++i) cout << setw (3) << dist[i] << ""; cout <<endl;cout << "path:" << ""; for (int i=0; i<num; ++i) cout << setw (3) << path[i] << "";d elete []dist;delete []path;} Template <typename T, typename e>void graph_mtx<t, E>::critical_path (const t& vert) {int num = This->ge T_numvertices (); int *early_start = new Int[num];int *late_start = new Int[num];assert (Early_start! = nullptr &AMP;&Amp  Late_start! = nullptr); int index = Get_vertex_index (vert); assert (Index! =-1); for (int i=0; i<num; ++i) early_start[i] = 0;for (int i=0; i<num; ++i) {int neighbor_index = Get_firstneighbor (Get_vertex_symbol (i)); while (neighbor_index! =-1) {int weight = edge[i][neighbor_index];if (Early_start[i]+weight > Early_start[neighbor_index]) early_start[ Neighbor_index] = Early_start[i]+weight;neighbor_index = Get_nextneighbor (Get_vertex_symbol (i), Get_vertex_symbol ( Neighbor_index));}} for (int i=0; i<num; ++i) cout << early_start[i] << ""; cout << endl;for (int i=0; i<num; ++i) Late_start[i] = max_cost;late_start[num-1] = early_start[num-1];for (int i=num-2; i>=0;-I.) {int neighbor_index = Get_firstneighbor (Get_vertex_symbol (i)); while (neighbor_index! =-1) {int weight = edge[i][neighbor_index];if (late_ Start[neighbor_index]-weight < Late_start[i]) late_start[i] = Late_start[neighbor_index]-weight;neighbor_index =            Get_nextneighbor (Get_vertex_symbol (i),                  Get_vertex_symbol (Neighbor_index));}} for (int i=0; i<num; ++i) cout << late_start[i] << ""; cout << endl;for (int i=0; i<num; ++i) if (early_start[i] = = Late_start[i]) cout << get_vertex_symbol (i) << "";d elete []early_start;delete [] Late_start;}
Test file:
#include "graph.h" #include "graph_mtx.h" int main () {Graph_mtx<char, int> Gm;//critical_pathgm.insert_vertex (' A '); Gm.insert_vertex (' B '); Gm.insert_vertex (' C '); Gm.insert_vertex (' D '); Gm.insert_vertex (' E '); Gm.insert_vertex (' F '); Gm.insert_vertex (' G '); Gm.insert_vertex (' H '); Gm.insert_vertex (' I '); Gm.insert_edge (' A ', ' B ', 6); Gm.insert_edge (' A ', ' C ', 4); Gm.insert_edge (' A ', ' d ', 5); Gm.insert_edge (' B ', ' e ', 1); Gm.insert_edge (' C ', ' e ', 1); Gm.insert_edge (' d ', ' F ', 2); Gm.insert_edge (' E ', ' G ', 9); Gm.insert_edge (' E ', ' H ', 7); Gm.insert_edge (' G ', ' I ', 2); Gm.insert_edge (' H ', ' I ', 5); Gm.insert_edge (' F ', ' H ', 4); Gm.critical_path (' a '); cout << Endl; #if 0//shortest_pathgm.insert_vertex (' a '); Gm.insert_vertex (' B '); Gm.insert_vertex (' C '); Gm.insert_vertex (' D '); Gm.insert_vertex (' E '); Gm.insert_edge (' A ', ' B ' , Gm.insert_edge (' A ', ' D ', '), Gm.insert_edge (' A ', ' e ', '), Gm.insert_edge (' B ', ' C ', '), Gm.insert_edge (' C ', ' e ', Gm.insert_edge (' d ', ' C '), Gm.insert_edge (' d ', ' E ', max), cout << "shortest_path: "<< endl;gm.shortest_path (' a '); cout << Endl; #endif # if 0//topological_sortgm.insert_vertex (' a '); Gm.insert_vertex (' B '); Gm.insert_vertex (' C '); Gm.insert_vertex (' D '); Gm.insert_vertex (' E '); Gm.insert_vertex (' F '); Gm.insert_edge (' A ', ' B ', 6); Gm.insert_edge (' A ', ' C ', 1); Gm.insert_edge (' A ', ' D ', 5); Gm.insert_edge (' C ', ' B ', 5); Gm.insert_edge (' C ', ' e ', 3); Gm.insert_edge (' d ', ' E ', 5); Gm.insert_edge (' f ', ' e ', 4); Gm.insert_edge (' F ', ' d ', 2); cout << "Topological_sort:" << endl;gm.topological_sort (); cout << Endl; #endifreturn 0;}
Some test results:

Topological ordering, critical path and shortest path algorithm of graphs--C + + implementation

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.