Data structure (shortest path)

I haven't systematically studied JAVA yet, so this note studies the shortest path problem of graph in data structure C language version.

route

Considering the weighted digraph, the sum of the weights of the edges on a road force (only considering a simple path) is defined as the path length or weighted path length of the path

There may be more than one path from the source point to the end point. The path with the shortest path length is called the shortest path. In many cases, the shortest path of two vertices is not necessarily unique, but the shortest path length must be unique.

Shortest path algorithm

Dijkstra algorithm

Problem: given a weighted digraph g and source point v, find the shortest path from V to other vertices in G, and limit the weight on each edge to be greater than or equal to 0.

The single source shortest path problem can be solved by Dijkstra algorithm

Basic ideas

Let G=(V,E) be a weighted directed graph, and divide the vertex set V in the graph into two groups:

——The first group is the set of vertices for which the shortest path has been found (represented by S. at the beginning, there is only one source point in S. after each shortest path v,..., u is found, u is added to the set s until all vertices are added to s, and the algorithm ends)

——The second group is the set of other vertices (represented by U) for which the shortest path is not found. The vertices of the second group are added to S in the order of increasing the length of the shortest path

 

Specific steps

(1) Initialization: S only contains the source point, that is, S={v}, and the shortest path of v is 0. U contains other vertices except v, and the distance of vertex i in U is the weight on the edge (if v and I have edges < v, I >) or infinite (if I is not the edge adjacent contact of v).

(2) select a vertex u with the smallest distance v from u and add u to S (the selected distance is the shortest path length from v to U).

(3) Take u as the newly considered middle point, modify the shortest path length of each vertex j  in U: if the shortest path length (passing through vertex u) from source point v to j (j belongs to U) is shorter than the original shortest path length (not passing through vertex u), modify the shortest path length of vertex j.

(4) repeat (2) and (3) until all vertices are included in S.

 

 

Algorithm design

How to store the shortest path length:

Stored in a one-dimensional array dist [j]. By default, dist [j] represents the shortest path length from the source point to v ertex j.

How to store the shortest path:

There are n-1 shortest paths from the source point to other vertices. One shortest path is represented by a one-dimensional array, and all n-1 shortest paths can be stored by a two-dimensional array path [] [].

The corresponding Dijkstra algorithm is as follows:

void Dijkstra(MatGraph g,int v)	//Dijkstra algorithm
{	int dist[MAXV],path[MAXV];
	int S[MAXV];				//S[i]=1 indicates that vertex I is in s, and S[i]=0 indicates that vertex I is in U
	int Mindis,i,j,u;
	bool flag;
	for (i=0;i<g.n;i++)
	{	dist[i]=g.edges[v][i];	//Distance initialization
		S[i]=0;					//S [] empty
		if (g.edges[v][i]<INF)	//Path initialization
			path[i]=v;			//When there is an edge from vertex v to vertex i, the previous vertex of vertex I is v
		else
			path[i]=-1;			//When there is no edge from vertex v to vertex i, the previous vertex of vertex I is - 1
	}
	disp(dist,path,g.n);
	printf("(%d)Set vertex%d Add to S aggregate\n",++count,v);
	S[v]=1;path[v]=0;			//The source point number v is placed in S
	for (i=0;i<g.n-1;i++)		//Loop until the shortest path of all vertices is found
	{	Mindis=INF;				//Mindis sets the initial value of the maximum length
		for (j=0;j<g.n;j++)		//Select the vertex u that is not in S (i.e. in U) and has the minimum shortest path length
			if (S[j]==0 && dist[j]<Mindis) 
			{	u=j;
				Mindis=dist[j];
			}
		printf("  reach U Smallest vertex in%d\n",u);
		printf("(%d)Set vertex%d Add to S aggregate\n",++count,u);
		S[u]=1;					//Add vertex u to S
		flag=false;
		for (j=0;j<g.n;j++)		//Modify the shortest path of vertices that are not in S (that is, in U)
			if (S[j]==0)
			{
				if (g.edges[u][j]<INF)
				{
					flag=true;
					printf("  Consider vertices%d Adjacency point of%d:",u,j);
					if (dist[u]+g.edges[u][j]<dist[j])
					{
						dist[j]=dist[u]+g.edges[u][j];
						printf("Modify its shortest path length dist[%d]by%d,",j,dist[j]);
						path[j]=u;
						printf("Modify shortest path path[%d]by%d\n",j,u);
					}
					else
						printf("vertex%d The shortest path length of has not been modified\n",j);
				}
			}
		if (!flag)
			printf("   vertex%d There are no adjacent points not considered(Do not modify)\n",u);
		disp(dist,path,g.n);
	}
	Dispath(g,dist,path,S,v);	//Output shortest path
}

The Dispath() function that outputs the shortest path of a single source is as follows:

void Dispath(MatGraph g,int dist[],int path[],int S[],int v)
//Outputs all shortest paths from vertex v
{	int i,j,k;
	int apath[MAXV],d;					//Store a shortest path (reverse) and the number of vertices
	for (i=0;i<g.n;i++)					//Loop outputs the path from vertex v to i
		if (S[i]==1 && i!=v)
		{	printf("  From vertex%d To vertex%d The path length of is:%d\t Path is:",v,i,dist[i]);
			d=0; apath[d]=i;			//Add end point on path
			k=path[i];
			if (k==-1)					//No path
				printf("no path\n");
			else						//Output the path when it exists
			{	while (k!=v)
				{	d++; apath[d]=k;
					k=path[k];
				}
				d++; apath[d]=v;		//Add start point on path
				printf("%d",apath[d]);	//Output starting point first
				for (j=d-1;j>=0;j--)	//Then output other vertices
					printf(",%d",apath[j]);
				printf("\n");
			}
		}
}

Regardless of the output of the path, the time complexity of Dijkstra algorithm is O(n^2), where the number of vertices in n graph

Floyd algorithm

Problem: for a directed graph whose edge weight is greater than 0, for each vertex I is not equal to j, find the shortest path and the shortest path length between vertex i and vertex J.

The multi-source shortest path problem can be solved by Floyd algorithm

Algorithm idea

Suppose that the directed graph G = (V, e) is stored by adjacency matrix. Set A two-dimensional array A to store the shortest path length between the current vertices, and the component A [i] [j] represents the shortest path length from the current vertices I to j.

Recursion produces a matrix sequence:

A [i] [J]: the shortest path length where the vertex number on the path from I to j is not greater than k

 

Algorithm design

Store the shortest path length with two-dimensional array A:

A [i] [J] represents the shortest path length from I to j after considering vertices 0 ~ k.

The last a [i] [j] of the array represents the shortest path length from the final I to j.

Use the two-dimensional array path to store the shortest path:

Path [i] [J] represents the shortest path from I to j after considering vertices 0 ~ k.

The last path [i] [j] of the array represents the shortest path from the final I to j.

The corresponding Floyd algorithm is as follows:

void Floyd(MatGraph g)							//Floyd algorithm
{	int A[MAXV][MAXV],path[MAXV][MAXV];
	int i,j,k;
	for (i=0;i<g.n;i++)
		for (j=0;j<g.n;j++) 
		{	A[i][j]=g.edges[i][j];
			if (i!=j && g.edges[i][j]<INF)
				path[i][j]=i;					//When vertices i to j have edges
			else
				path[i][j]=-1;				//When vertices i to j have no edges
		}
	for (k=0;k<g.n;k++)						//Look at all vertices in turn
	{	for (i=0;i<g.n;i++)
			for (j=0;j<g.n;j++)
				if (A[i][j]>A[i][k]+A[k][j])
				{	A[i][j]=A[i][k]+A[k][j];	//Modify the shortest path length
					path[i][j]=path[k][j];		//Modify shortest path
				}
	}
	Dispath(g,A,path);							//Output shortest path
}

The Dispath() function that outputs the shortest path of multiple sources is as follows:

void Dispath(MatGraph g,int A[][MAXV],int path[][MAXV])
{	int i,j,k,s;
	int apath[MAXV],d;		//Store the middle vertex (reverse) of a shortest path and the number of vertices
	for (i=0;i<g.n;i++)
		for (j=0;j<g.n;j++)
		{	if (A[i][j]!=INF && i!=j)			//If there is a path between vertices i and j
			{	printf("  from%d reach%d The path to is:",i,j);
				k=path[i][j];
				d=0; apath[d]=j;				//Add end point on path
				while (k!=-1 && k!=i)			//Add middle point on path
				{	d++; apath[d]=k;
					k=path[i][k];
				}
				d++; apath[d]=i;				//Add start point on path
				printf("%d",apath[d]);			//Output starting point
				for (s=d-1;s>=0;s--)			//Middle vertex on output path
					printf(",%d",apath[s]);
				printf("\t Path length is:%d\n",A[i][j]);
			}
		}
}

Without considering the path output, the time complexity of Floyd algorithm is O(n^3), where n is the number of vertices in the graph.

compare

algorithmpurposeTime complexitycharacteristic
DijkstraSingle source shortest path

O(n^2)

Not suitable for negative weight
FloydMulti source shortest pathO(n^3)Not suitable for negative weight circuit

Keywords: data structure

Added by christo on Mon, 20 Dec 2021 18:59:29 +0200