Algorithm improvement: Dijkstra (Dijkstra) algorithm for graphs

Table of contents

concept

train of thought

the code


concept

Dijkstra algorithm (Dijkstra) was proposed by Dutch computer scientist Dijkstra in 1959, so it is also called Dijkstra algorithm. It is the shortest path algorithm from one vertex to other vertices, and it solves the shortest path problem in the weighted graph. The main feature of Dijkstra's algorithm is that it starts from the starting point, adopts the strategy of greedy algorithm, and traverses the adjacent nodes of the vertex that is the closest to the starting point and has not been visited each time until it extends to the end point.

Note that the algorithm requires that there are no negative weight edges in the graph, otherwise the algorithm will be trapped in a circle.

train of thought

Suppose our goal is to get from A to D

The basic idea is to maintain a path length table, each node is the key itself, because it starts from node A to node D, then the initial value of A is 0, and the rest of the values ​​are -1 (indicating that it has not yet arrived).

A

B

C

D

0

-1

-1

-1

Then start looking from A to find all the downstream nodes. We found that they can be B, C, and D, which are 2, 8, and 6 respectively. At this time, update the table:

A

B

C

D

0

2

8

6

Then the node A has been traversed, and there is no need to traverse it again. Close the item A, find the minimum value from all the remaining items, and then start the node with this value, and continue to look down, here is the node B.

The downstream of node B are D and C, which are 1 and 4 respectively, but because when starting from A to B, the length from A to B is 2, so the length from A to D and C is 3 and 6, we found If the value is smaller than the original value, the form is updated, and B is also closed.

A

B

C

D

0

2

6

3

Then I found that the shortest distance is D, and our destination is also D. At this time, the algorithm can actually end.

A brief summary is:

  1. Search downstream from the start node, update and maintain an open table, and the traversed nodes enter the close table;
  2. Find the minimum value that is not -1 from the open table, and use it as a new starting node to find the downstream;
  3. After finding the downstream, compare it with:
    1. If the value of the OPEN table of the downstream node is -1, it will be directly overwritten and its upstream node will be recorded, so as to trace the path later;
    2. If the OPNE table value of the downstream node is not -1, compare the path weight + the open table value of the starting node with it. If the ratio is smaller, add it and record its upstream node for later tracing the path;
    3. Until all nodes in the current Open table are closed, or the smallest node in the Open table is the target node.

This also explains why it is not possible to have negative weights, because once there are negative weights, the content of the previous form records will no longer be the "minimum value", especially in the case of a ring, the ring is the most rotated, and the value is smaller. The whole algorithm will entertain itself in the ring.

the code

#include<iostream>
#include<string>
using namespace std;
class Node{
public:
	Node()
	{
		minL=100;//初始化最短路径为无穷大。
	}
	char node;//节点名称
	int minL;//当前节点的最短路径
	Node* last;//下一个节点
};//定义从一个节点类
 
void print(Node *node)//最短路径函数的递归打印
{
	if (node == NULL)
	{
		return;
	}
	print(node->last);/*递归调用,先打印前面的节点*/
    cout << node->node << "->";
}
 
int main()
{
 
	int wvalue[8][8];//定义路径权重	
for (int a = 0; a < 8; a++)
	{
		for (int b = 0; b < 8; b++)
		{
			wvalue[a][b] = 1000;//初始化权值,如若两个点没有连接则为无穷大。
		}
	}
    wvalue[0][1] = 2;//根据图来设置各个点之间的路径。
	wvalue[0][2] = 5;
	wvalue[0][3] = 4;
	wvalue[1][6] = 12;
	wvalue[1][2] = 2;
	wvalue[1][4] = 7;
	wvalue[2][3] = 1;
	wvalue[2][4] = 4;
	wvalue[2][5] = 3;
	wvalue[3][5] = 4;
	wvalue[4][5] = 1;
	wvalue[4][7] = 5;
	wvalue[5][7] = 7;
	wvalue[6][7] = 3;
	Node node[8];//定义节点变量
	node[0].node = 'O';//命名各个节点
	node[0].last = NULL;//初始化前一个节点为空
	node[1].node = 'A';
	node[2].node = 'B';
	node[3].node = 'C';
	node[4].node = 'D';
	node[5].node = 'E';
	node[6].node = 'F';
	node[7].node = 'T';
	Node u;//定义当前被访问的节点
	Node S[8];//辅助变量存储8个节点
    int a = 0;
	for (int i = 0; i < 8;i++) //第一个循环遍历这8个节点
{
		u = node[i];//当前被遍历的节点
		if (i==0)
		{
		 u.minL = 0;//初始化第一个结点的最短路径	
	    }
		S[i] = node[i];//储存被遍历的节点
		for (int j = 0;j<8; j++)//遍一个节点与其他8个节点的两个路径权值	
        {
			if (u.minL + wvalue[i][j] < node[j].minL)/*如果当前节点的最短路径加上该节点到相邻节点的权重小于其下一个节点路径的权重,则更新其下一个节点路径的最小距离*/	
        	{
				node[j].minL = u.minL + wvalue[i][j];
				node[j].last = &S[i];
 
			}
		}
}
	cout << node[7].minL << endl;//打印最短路径
	print(&node[7]);
	return 0;
}

 

Guess you like

Origin blog.csdn.net/qq_32378713/article/details/128073478