Dijkstra algorithm learning summary

1. Realize with adjacency matrix (to be filled...)

2. Realize with adjacency list

adjacency list definition

#define MaxVertexnum 100 //最大顶点数量
int dis[MaxVertexnum] = { 0 }; //单源最短路径
bool vis[MaxVertexnum] = { 0 }; //访问标志位
#define INF 0x7fffffff //最大值
#define VertexType int //顶点类型
#define InfoType int //边权重类型

typedef struct ArcNode{
    int adjvex; //边指向结点
	InfoType info; //边权重
	struct ArcNode* next;
};

typedef struct VNode {
	VertexType name;
	ArcNode* first;
}AdjList[MaxVertexnum];

typedef struct {
	AdjList node;
	int vexnum;
	int arcnum;
}ALGraph;

Concrete understanding, a total of three structures are connected to each other, which can be compared to the child brother representation and radix sorting of the tree and the zipper method of the hash table. The three have the same effect

 dijkstra achieves

  1. First find the unvisited point u with the smallest distance in the current dis[] distance list
  2. If not found, it means that the shortest distance of all points has been calculated
  3. If found, take out all adjacent points of u, calculate and update the shortest distance
  4. Go back to step (1) and continue until the operation is complete
void dijkstra(ALGraph* G, int start) {
	fill(vis, vis + MaxVertexnum, 0); //访问标志初始化
	fill(dis, dis + MaxVertexnum, INF); //路径初始化
	dis[start] = 0; //源点到自己的距离为0
	int i, j, u, min;
	for (i = 0; i < G->vexnum; i++) {
		u = -1; //在未被访问过的顶点中找到距离最短的点
		min = INF;
		for (j = 1; j <= G->vexnum; j++) {  
			if (vis[j] = false && dis[j] < min) {
				u = j; 
				min = dis[j];
			}
		}
		if (u == -1) return; //所有顶点均已访问
		vis[u] = true;
		ArcNode* tmp = G->node[u].first; //找到距离最短的顶点u的邻接点
		printf("\n\n\n");
		while (tmp) {
			//若该邻接点未被访问过 且 源点到u的最短距离+u到该邻接点的距离小于该邻接点此前的最短距离
			if (vis[tmp->adjvex] == false && dis[u] + tmp->info < dis[tmp->adjvex]) 
				dis[tmp->adjvex] = dis[u] + tmp->info;
			tmp = tmp->next; //继续访问u的下一个邻接点
		}
	}

}

 3. Abstract implementation of Dijkstra's algorithm template (for questions)

#include <bits/stdc++.h>
using namespace std;
struct node {
	int id, dis;
	bool friend operator < (const node& a, const node& b) {
		return a.dis > b.dis;
	}
};
int n, m, s;
int ui, vi, wi;
vector<pair<int, int>> E[100];
int dis[100];
int vis[100];
void dijkstra() {
	fill(dis, dis + 100, 1e9); //初始化dis列表
	dis[s] = 0;
	priority_queue<node> Q;
	Q.push(node{ s, 0 });
	while (!Q.empty()) {
		int Now = Q.top().id; //当前Now顶点的距离最短
		int D = Q.top().dis; //D为Now顶点目前的最短距离
		Q.pop();
		//对应底下①语句,因每次更新数据都会把距离放进列表,故当计算完所有距离后依旧留下一堆无用数据,用此语句进行过滤
		if (vis[Now]) continue; 
		vis[Now] = 1;
		for (auto it : E[Now]) { //访问Now的所有邻边
			int des = it.first;
			int weigh = it.second;
			if (dis[des] > D + weigh) { //源点到Now的距离+Now到des的距离 < 先前des的最短距离
				dis[des] = D + weigh;
				Q.push(node{ des, dis[des] }); //①
			}
		}
	}
}
int main() {
	cin >> n >> m >> s; //n:顶点数	m:边数,s:源点
	for (int i = 0; i < m; i++) {
		cin >> ui >> vi >> wi; //从ui到vi权重为wi的一条边
		E[ui].push_back({ vi,wi });
	}
	dijkstra();
	for (int i = 1; i <= n; i++) {
		printf("%d ", dis[i]);
	}

	return 0;
}

 The template can be understood concretely by the following figure

 If you want to get this picture, you should enter the data in this way, and compare the input data with the abstract structure on the right of the above picture, and you can find the inner connection

5 8 0
0 1 1
0 2 2
0 4 1
2 1 3
2 3 2
2 4 2
3 4 1
3 1 2

Input and output samples

 input#1

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4

Output #1

0 2 4 3

4. Floyd algorithm

Add a Floyd algorithm as a complement

int n;
int A[100][100], path[100][100];
void floyd() {
	fill(path, path + 10000, -1); //初始化path数组为-1
	for (int k = 0; k < n; k++) { //考虑以Vk作为中转点
		for (int i = 0; i < n; i++) { //遍历整个矩阵,i为行号,j为列号
			for (int j = 0; j < n; j++) { 
				if (A[i][j] > A[i][k] + A[k][j]) { //以Vk为中转点的路径更短
					A[i][j] = A[i][k] + A[k][j]; //更新最短路径长度
					path[i][j] = k; //中转点
				}
			}
		}
	}
}

おすすめ

転載: blog.csdn.net/qq_21891843/article/details/126324602