/*
* Copyright (c)2017, School of Computer and Control Engineering, Yantai University
*All rights reservrd.
* Author: Li Xinhao
* Completion time: 16 November 2017
* Version number: v1.0
* Problem Description: Assuming that graph G is stored in adjacent table, the following algorithms are designed and implemented respectively. It is required that graph different from the example be tested several times, and the method of dealing with related problems is mastered by observing the output value.
(1) Design an algorithm to determine whether there is a simple path from vertex u to v.
(2) Designing a simple path from vertex u to v in the algorithm output graph G (ensuring that there is at least one simple path from vertex u to v in the graph G when designing the test graph).
(3) Output all simple paths from vertex u to v.
(4) All simple paths from vertex u to v in output graph G are s in length.
(5) Find all simple loops (if any) passing through a vertex k in the graph
1. Establishing a new project using graph algorithm library header file graph.
#ifndef GRAPH_H_INCLUDED #define GRAPH_H_INCLUDED #define MAXV 100//Maximum number of vertices #Define INF 32767//INF Representation ____________ typedef int InfoType; //The following defines the type of adjacency matrix typedef struct { int no; //Vertex number InfoType info; //Other vertex information, where the weights of weighted graphs are stored } VertexType; //Vertex Type typedef struct //Definition of Graphs { int edges[MAXV][MAXV]; //adjacency matrix int n,e; //Number of vertices, arcs VertexType vexs[MAXV]; //Store vertex information } MGraph; //Types of Adjacency Matrix of Graphs //The following defines the adjacency table type typedef struct ANode //Node Structure Types of Arcs { int adjvex; //The end point of the arc struct ANode *nextarc; //A pointer to the next arc InfoType info; //The information about this arc is used here to store weights } ArcNode; typedef int Vertex; typedef struct Vnode //Types of adjacent header nodes { Vertex data; //Vertex information int count; //Store vertex entry, only for topological sorting ArcNode *firstarc; //Point to the first arc } VNode; typedef VNode AdjList[MAXV]; //AdjList is an adjacency table type typedef struct { AdjList adjlist; //Adjacency list int n,e; //Vertex number n and edge number e in Graphs } ALGraph; //Types of Adjacency Table of Graphs //Function: A graph stored with adjacency matrix is constructed from a two-dimensional array reflecting the vertex adjacency relationship in the graph. //Parameter: Arr - Array name. Since the number of elements per row must be given when the formal parameter is a two-dimensional array, the parameter Arr is declared as a one-dimensional array name (pointer to int). // The Order of n-Matrix // g - The adjacency matrix data structure to be constructed void ArrayToMat(int *Arr, int n, MGraph &g); //Constructing Adjacency Matrix of Graph with Ordinary Array void ArrayToList(int *Arr, int n, ALGraph *&); //Constructing Adjacency List of Graphs with Ordinary Array void MatToList(MGraph g,ALGraph *&G);//Converting Adjacency Matrix g into Adjacency Table G void ListToMat(ALGraph *G,MGraph &g);//Converting Adjacency Table G into Adjacency Matrix G void DispMat(MGraph g);//Output adjacency matrix g void DispAdj(ALGraph *G);//Output adjacency table G
Define these functions in source files
#include <stdio.h> #include <malloc.h> #include "graph.h" //Function: A graph stored with adjacency matrix is constructed from a two-dimensional array reflecting the vertex adjacency relationship in the graph. //Parameter: Arr - Array name. Since the number of elements per row must be given when the formal parameter is a two-dimensional array, the parameter Arr is declared as a one-dimensional array name (pointer to int). // The Order of n-Matrix // g - The adjacency matrix data structure to be constructed void ArrayToMat(int *Arr, int n, MGraph &g) { int i,j,count=0; //Count is used to count edges, i.e. the number of non-zero elements in a matrix g.n=n; for (i=0; i<g.n; i++) for (j=0; j<g.n; j++) { g.edges[i][j]=Arr[i*n+j]; //Considering Arr as a two-dimensional array of n * n, Arr[i*n+j] is Arr[i][j]. The application of calculating storage location if(g.edges[i][j]!=0 && g.edges[i][j]!=INF) count++; } g.e=count; } void ArrayToList(int *Arr, int n, ALGraph *&G) { int i,j,count=0; //Count is used to count edges, i.e. the number of non-zero elements in a matrix ArcNode *p; G=(ALGraph *)malloc(sizeof(ALGraph)); G->n=n; for (i=0; i<n; i++) //Initial value of pointer field for all header nodes in adjacent table G->adjlist[i].firstarc=NULL; for (i=0; i<n; i++) //Check each element in the adjacency matrix for (j=n-1; j>=0; j--) if (Arr[i*n+j]!=0) //There is an edge. Arr is regarded as a two-dimensional array of n * n. Arr[i*n+j] is Arr[i][j] { p=(ArcNode *)malloc(sizeof(ArcNode)); //Create a node*p p->adjvex=j; p->info=Arr[i*n+j]; p->nextarc=G->adjlist[i].firstarc; //Insertion of *p by head insertion G->adjlist[i].firstarc=p; } G->e=count; } void MatToList(MGraph g, ALGraph *&G) //Converting Adjacency Matrix g into Adjacency Table G { int i,j; ArcNode *p; G=(ALGraph *)malloc(sizeof(ALGraph)); for (i=0; i<g.n; i++) //Initial value of pointer field for all header nodes in adjacent table G->adjlist[i].firstarc=NULL; for (i=0; i<g.n; i++) //Check each element in the adjacency matrix for (j=g.n-1; j>=0; j--) if (g.edges[i][j]!=0) //There is an edge. { p=(ArcNode *)malloc(sizeof(ArcNode)); //Create a node*p p->adjvex=j; p->info=g.edges[i][j]; p->nextarc=G->adjlist[i].firstarc; //Insertion of *p by head insertion G->adjlist[i].firstarc=p; } G->n=g.n; G->e=g.e; } void ListToMat(ALGraph *G,MGraph &g) //Converting Adjacency Table G into Adjacency Matrix G { int i,j; ArcNode *p; g.n=G->n; //According to the first floor classmates "report" to change. g.n is not assigned and the following initialization does not work g.e=G->e; for (i=0; i<g.n; i++) //Initialize the adjacency matrix first for (j=0; j<g.n; j++) g.edges[i][j]=0; for (i=0; i<G->n; i++) //Assignment of adjacency matrix based on adjacency table { p=G->adjlist[i].firstarc; while (p!=NULL) { g.edges[i][p->adjvex]=p->info; p=p->nextarc; } } } void DispMat(MGraph g) //Output adjacency matrix g { int i,j; for (i=0; i<g.n; i++) { for (j=0; j<g.n; j++) if (g.edges[i][j]==INF) printf("%3s","∞"); else printf("%3d",g.edges[i][j]); printf("\n"); } } void DispAdj(ALGraph *G) //Output adjacency table G { int i; ArcNode *p; for (i=0; i<G->n; i++) { p=G->adjlist[i].firstarc; printf("%3d: ",i); while (p!=NULL) { printf("-->%d/%d ",p->adjvex,p->info); p=p->nextarc; } printf("\n"); } }
3. Implementing Testing
(1) Determine whether there is a simple path from vertex u to v.
The source functions are as follows:
#include <stdio.h> #include <malloc.h> #include "graph.h" int visited[MAXV]; //Global array defining access flags for storage nodes void ExistPath(ALGraph *G,int u,int v, bool &has) { int w; ArcNode *p; visited[u]=1; if(u==v) { has=true; return; } p=G->adjlist[u].firstarc; while (p!=NULL) { w=p->adjvex; if (visited[w]==0) ExistPath(G,w,v,has); p=p->nextarc; } } void HasPath(ALGraph *G,int u,int v) { int i; bool flag = false; for (i=0; i<G->n; i++) visited[i]=0; //Access flag array initialization ExistPath(G,u,v,flag); printf(" from %d reach %d ", u, v); if(flag) printf("There are simple paths\n"); else printf("No Simple Path\n"); } int main() { ALGraph *G; int A[5][5]= { {0,0,0,0,0}, {0,0,1,0,0}, {0,0,0,1,1}, {0,0,0,0,0}, {1,0,0,1,0}, }; //Please draw the corresponding digraph. ArrayToList(A[0], 5, G); HasPath(G, 1, 0); HasPath(G, 4, 1); return 0; }
The screenshots of the test results are as follows:
(2) A simple path from vertex u to v in output graph G (when designing test graph, ensure that there is at least one simple path from vertex u to v in graph G).
#include <stdio.h> #include <malloc.h> #include "graph.h" int visited[MAXV]; //Global array defining access flags for storage nodes void FindAPath(ALGraph *G,int u,int v,int path[],int d) { //d denotes the path length in path, initially - 1 int w,i; ArcNode *p; visited[u]=1; d++; path[d]=u; //The path length d is increased by 1, and the vertex u is added to the path. if (u==v) //Find a path, output and return { printf("A simple path is:"); for (i=0; i<=d; i++) printf("%d ",path[i]); printf("\n"); return; //Find a path and return } p=G->adjlist[u].firstarc; //p points to the first adjacent point of vertex u while (p!=NULL) { w=p->adjvex; //The number of adjacent points is w if (visited[w]==0) FindAPath(G,w,v,path,d); p=p->nextarc; //p points to the next adjacent point of vertex u } } void APath(ALGraph *G,int u,int v) { int i; int path[MAXV]; for (i=0; i<G->n; i++) visited[i]=0; //Access flag array initialization FindAPath(G,u,v,path,-1); //The initial value of D is - 1, and d++ becomes 0 when called. } int main() { ALGraph *G; int A[5][5]= { {0,0,0,0,0}, {0,0,1,0,0}, {0,0,0,1,1}, {0,0,0,0,0}, {1,0,0,1,0}, }; //Please draw the corresponding digraph. ArrayToList(A[0], 5, G); APath(G, 1, 0); APath(G, 4, 1); return 0; }
Test results:
(3) Output all simple paths from vertex u to v.
#include <stdio.h> #include <malloc.h> #include "graph.h" int visited[MAXV]; //Global array defining access flags for storage nodes void FindPaths(ALGraph *G,int u,int v,int path[],int d) //d is the length of the path that has been traveled so far, and the initial value is -1 at the time of invocation. { int w,i; ArcNode *p; visited[u]=1; d++; //Increase path length by 1 path[d]=u; //Add the current vertex to the path if (u==v && d>1) //Output a path { printf(" "); for (i=0; i<=d; i++) printf("%d ",path[i]); printf("\n"); } p=G->adjlist[u].firstarc; //p points to the first edge of u while(p!=NULL) { w=p->adjvex; //Adjacent vertices with w as u if (visited[w]==0) //If the vertex is unlabeled, it is accessed recursively FindPaths(G,w,v,path,d); p=p->nextarc; //Find the next adjacent vertex of u } visited[u]=0; //Restore environment } void DispPaths(ALGraph *G,int u,int v) { int i; int path[MAXV]; for (i=0; i<G->n; i++) visited[i]=0; //Access flag array initialization printf("from%d reach%d All paths:\n",u,v); FindPaths(G,u,v,path,-1); printf("\n"); } int main() { ALGraph *G; int A[5][5]= { {0,1,0,1,0}, {1,0,1,0,0}, {0,1,0,1,1}, {1,0,1,0,1}, {0,0,1,1,0} }; //Please draw the corresponding digraph. ArrayToList(A[0], 5, G); DispPaths(G, 1, 4); return 0; }
Test results:
(4) All simple paths from vertex u to vertex v in output graph G with length s.
#include <stdio.h> #include <malloc.h> #include "graph.h" int visited[MAXV]; //Global array defining access flags for storage nodes void SomePaths(ALGraph *G,int u,int v,int s, int path[],int d) //d is the length of the path that has been traveled so far, and the initial value is -1 at the time of invocation. { int w,i; ArcNode *p; visited[u]=1; d++; //Increase path length by 1 path[d]=u; //Add the current vertex to the path if (u==v && d==s) //Output a path { printf(" "); for (i=0; i<=d; i++) printf("%d ",path[i]); printf("\n"); } p=G->adjlist[u].firstarc; //p points to the first edge of u while(p!=NULL) { w=p->adjvex; //Adjacent vertices with w as u if (visited[w]==0) //If the vertex is unlabeled, it is accessed recursively SomePaths(G,w,v,s,path,d); p=p->nextarc; //Find the next adjacent vertex of u } visited[u]=0; //Restore environment } void DispSomePaths(ALGraph *G,int u,int v, int s) { int i; int path[MAXV]; for (i=0; i<G->n; i++) visited[i]=0; //Access flag array initialization printf("from%d reach%d Chang Wei%d Path:\n",u,v,s); SomePaths(G,u,v,s,path,-1); printf("\n"); } int main() { ALGraph *G; int A[5][5]= { {0,1,0,1,0}, {1,0,1,0,0}, {0,1,0,1,1}, {1,0,1,0,1}, {0,0,1,1,0} }; //Please draw the corresponding digraph. ArrayToList(A[0], 5, G); DispSomePaths(G, 1, 4, 3); return 0; }
Test results:
(5) Find all simple loops (if they exist) passing through a vertex k in the graph
#include <stdio.h> #include <malloc.h> #include "graph.h" int visited[MAXV]; //global variable void DFSPath(ALGraph *G,int u,int v,int path[],int d) //d is the length of the path that has been traveled so far, and the initial value is -1 at the time of invocation. { int w,i; ArcNode *p; visited[u]=1; d++; path[d]=u; p=G->adjlist[u].firstarc; //p points to the first edge of vertex u while (p!=NULL) { w=p->adjvex; //w is the adjacent point of vertex u if (w==v && d>0) //Find a loop and output it. { printf(" "); for (i=0; i<=d; i++) printf("%d ",path[i]); printf("%d \n",v); } if (visited[w]==0) //If w is not accessed, it is accessed recursively DFSPath(G,w,v,path,d); p=p->nextarc; //Find the next adjacent vertex of u } visited[u]=0; //Recovery environment: make the vertex reusable } void FindCyclePath(ALGraph *G,int k) //Output all loops passing through vertex k { int path[MAXV],i; for (i=0; i<G->n; i++) visited[i]=0; //Access flag array initialization printf("After vertex%d All loops\n",k); DFSPath(G,k,k,path,-1); printf("\n"); } int main() { ALGraph *G; int A[5][5]= { {0,1,1,0,0}, {0,0,1,0,0}, {0,0,0,1,1}, {0,0,0,0,1}, {1,0,0,0,0} }; //Please draw the corresponding digraph. ArrayToList(A[0], 5, G); FindCyclePath(G, 0); return 0; }
Test results: