#include <stdio.h> #include <stdlib.h> #include <limits.h> #define MAX_VERTICES 100 #define INF INT_MAX typedef struct Graph { int V; //顶点数 int E; //边数 int adj[MAX_VERTICES][MAX_VERTICES];//邻接矩阵 } Graph; void init_graph(Graph* G, int V) { G->V = V; G->E = 0; for (int i = 0; i < G->V; i++) { for (int j = 0; j < G->V; j++) { G->adj[i][j] = INF; } } } void add_edge(Graph* G, int u, int v, int w) { G->adj[u][v] = w; G->adj[v][u] = w; G->E++; } void dijkstra(Graph* G, int s, int dist[]) { int visited[MAX_VERTICES] = { 0 }; for (int i = 0; i < G->V; i++) { dist[i] = INF; } dist[s] = 0; for (int i = 0; i < G->V; i++) { int u = -1; for (int j = 0; j < G->V; j++) { if (!visited[j] && (u == -1 || dist[j] < dist[u])) { u = j; } } visited[u] = 1; for (int v = 0; v < G->V; v++) { if (G->adj[u][v] != INF) { if (dist[u] + G->adj[u][v] < dist[v]) { dist[v] = dist[u] + G->adj[u][v]; } } } } } int main() { Graph G; int V = 6; init_graph(&G, V); add_edge(&G, 0, 1, 10); add_edge(&G, 0, 2, 3); add_edge(&G, 1, 2, 1); add_edge(&G, 1, 3, 2); add_edge(&G, 2, 1, 4); add_edge(&G, 2, 3, 8); add_edge(&G, 2, 4, 2); add_edge(&G, 3, 4, 7); add_edge(&G, 3, 5, 1); add_edge(&G, 4, 5, 5); int dist[MAX_VERTICES]; dijkstra(&G, 0, dist); printf("最短路径长度为:%d\n", dist[V - 1]); return 0; }代码解读
时间: 2024-03-31 08:32:38 浏览: 83
这是一个使用邻接矩阵实现的Dijkstra算法的代码。首先定义了一个图的结构体,包括顶点数、边数和邻接矩阵。然后定义了初始化图的函数和添加边的函数。接着是Dijkstra算法的实现,在算法中用visited数组记录已经访问过的顶点,用dist数组记录源点到各个顶点的最短距离,算法的核心循环是通过选择dist数组中最小的未访问过的顶点来进行松弛操作。最后在主函数中构造了一个图,并计算了从顶点0到顶点5的最短路径长度。
相关问题
dijkstra算法c++代码实现。输入:第一行,三个整数,$vn,en,s $,用空格分开,分别表示图G中:顶点数目(顶点编号从0开始),弧的数量(无向图每对顶点之间有两条弧),Dijkstra算法指定的起点。其中:1≤ vn ≤ 1000, 1≤ en ≤ vn×(vn-1)。注意:案例中提供的弧可以有重复的,图应该按照最后一次的弧的设置为准,即SetEdge的语义当存在该弧时,设置权值。 之后会有en行,每行表示一对顶点之间的一条弧,形式为:"<"+from+", "+to+", "+weight+">",其中from为弧的起点,to为弧的终点,weight为弧上权值(每对顶点之间的不同的弧上的权值可以不同)输出:共vn行,第i行表示编号为i的顶点(第i个顶点,i从0开始)到起点s的最短路径长度len,以及该最短路径中的前驱顶点p(起始顶点s的前驱设为自身顶点编号s)。示例:输入10 32 0 <2, 1, 2> <1, 2, 2> <5, 8, 52> <8, 5, 52> <1, 7, 141> <7, 1, 141> <0, 8, 185> <8, 0, 185> <3, 8, 43> <8, 3, 43> <7, 8, 136> <8, 7, 136> <1, 2, 122> <2, 1, 122> <6, 8, 150> <8, 6, 150> <2, 1, 6> <1, 2, 6> <6, 3, 16> <3, 6, 16> <7, 9, 34> <9, 7, 34> <3, 1, 10> <1, 3, 10> <8, 9, 193> <9, 8, 193> <7, 8, 49> <8, 7, 49> <0, 1, 198> <1, 0, 198> <0, 5, 179> <5, 0, 179>输出:<0, 0, 0> <1, 198, 0> <2, 204, 1> <3, 208, 1> <4, INF, 0> <5, 179, 0> <6, 224, 3> <7, 234, 8> <8, 185, 0> <9, 268, 7>
以下是Dijkstra算法的C语言代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_VERTICES 1000
#define INF INT_MAX
typedef struct {
int vertex; // 边的终点
int weight; // 边的权重
struct EdgeNode *next;
} EdgeNode; // 边的节点
typedef struct {
EdgeNode *first; // 第一条边
} VertexNode; // 顶点的节点
int vn, en, s; // 顶点数目,弧的数量,起点
VertexNode graph[MAX_VERTICES]; // 图的邻接表
// 添加一条边
void SetEdge(int from, int to, int weight) {
EdgeNode *p = graph[from].first;
// 如果该顶点没有边,则新建一条边
if (p == NULL) {
p = (EdgeNode*)malloc(sizeof(EdgeNode));
p->vertex = to;
p->weight = weight;
p->next = NULL;
graph[from].first = p;
return;
}
// 查找是否已经存在该边
while (p->next != NULL) {
if (p->vertex == to) {
p->weight = weight; // 如果已经存在该边,则更新权值
return;
}
p = p->next;
}
// 如果不存在该边,则新建一条边
if (p->vertex != to) {
EdgeNode *q = (EdgeNode*)malloc(sizeof(EdgeNode));
q->vertex = to;
q->weight = weight;
q->next = NULL;
p->next = q;
} else {
p->weight = weight; // 如果已经存在该边,则更新权值
}
}
// Dijkstra算法
void Dijkstra(int s, int *len, int *p) {
int i, j, v, min;
int visited[MAX_VERTICES]; // 标记每个顶点是否已被访问
EdgeNode *p_node;
// 初始化距离和前驱
for (i = 0; i < vn; i++) {
visited[i] = 0;
len[i] = INF;
p[i] = -1;
}
len[s] = 0;
// 进行vn次循环,每次找到一个未被访问的距离最小的顶点v
for (i = 0; i < vn; i++) {
v = -1;
min = INF;
for (j = 0; j < vn; j++) {
if (!visited[j] && len[j] < min) {
v = j;
min = len[j];
}
}
// 如果未找到未被访问的顶点,则退出循环
if (v == -1) {
break;
}
// 标记该顶点为已访问
visited[v] = 1;
// 对v的每一条边进行松弛操作
p_node = graph[v].first;
while (p_node != NULL) {
if (!visited[p_node->vertex] && len[v] + p_node->weight < len[p_node->vertex]) {
len[p_node->vertex] = len[v] + p_node->weight;
p[p_node->vertex] = v;
}
p_node = p_node->next;
}
}
}
int main() {
int i, from, to, weight;
int len[MAX_VERTICES], p[MAX_VERTICES];
// 读入顶点数目,弧的数量和起点
scanf("%d%d%d", &vn, &en, &s);
// 读入每一条边并添加到邻接表中
for (i = 0; i < en; i++) {
scanf("<%d, %d, %d>", &from, &to, &weight);
SetEdge(from, to, weight);
}
// 运行Dijkstra算法
Dijkstra(s, len, p);
// 输出结果
for (i = 0; i < vn; i++) {
printf("<%d, %d, %d>\n", i, len[i], p[i]);
}
return 0;
}
```
请设计void Dijkstra(Graph g, int s, int D[], int P[])函数。 该函数计算编号为s的顶点到所有顶点的最短路径长度及最短路径。 如果顶点不可达,则最短路径为INT_MAX。 数组D[]记录顶点s到对应顶点的最短距离(s到s的最短路径长度为0) 数组P[]记录顶点s到对应顶点的最短路径上的前驱(s到s的前驱为s)。 请注意,本题有预置代码,只需提交所要求的函数定义代码即可。邻接表,用c
以下是Dijkstra函数的代码实现,使用了邻接表来表示图:
```c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_VERTICES 1000
typedef struct _Edge {
int to;
int weight;
struct _Edge* next;
} Edge;
typedef struct _Graph {
Edge* adj[MAX_VERTICES];
int num_vertices;
} Graph;
void addEdge(Graph* g, int from, int to, int weight) {
Edge* e = (Edge*)malloc(sizeof(Edge));
e->to = to;
e->weight = weight;
e->next = g->adj[from];
g->adj[from] = e;
}
void Dijkstra(Graph g, int s, int D[], int P[]) {
const int n = g.num_vertices;
int visited[n];
for (int i = 0; i < n; i++) {
D[i] = INT_MAX;
P[i] = -1;
visited[i] = 0;
}
D[s] = 0;
for (int i = 0; i < n - 1; i++) {
int u = -1;
for (int j = 0; j < n; j++) {
if (!visited[j] && (u == -1 || D[j] < D[u])) {
u = j;
}
}
visited[u] = 1;
for (Edge* e = g.adj[u]; e != NULL; e = e->next) {
int v = e->to;
if (!visited[v] && D[u] + e->weight < D[v]) {
D[v] = D[u] + e->weight;
P[v] = u;
}
}
}
}
int main() {
int n, m, s;
scanf("%d%d%d", &n, &m, &s);
Graph g;
g.num_vertices = n;
for (int i = 0; i < n; i++) {
g.adj[i] = NULL;
}
for (int i = 0; i < m; i++) {
int from, to, weight;
scanf("%d%d%d", &from, &to, &weight);
addEdge(&g, from, to, weight);
}
int D[MAX_VERTICES], P[MAX_VERTICES];
Dijkstra(g, s, D, P);
for (int i = 0; i < n; i++) {
if (D[i] == INT_MAX) {
printf("INT_MAX\n");
} else {
printf("%d\n", D[i]);
}
}
return 0;
}
```
在该函数实现中,我们首先定义了邻接表数据结构,然后通过addEdge函数来添加边。Dijkstra函数使用了类似于邻接矩阵的实现方式,但是针对每个顶点只存储了邻接表中的链表头指针,而不是一个完整的链表。在每次循环中,我们从未访问过的顶点中选取距离起点最近的顶点,将该顶点标记为已访问,并更新起点到其它未访问顶点的最短距离及最短路径。最终,D数组中记录了起点s到各顶点的最短距离,P数组中记录了起点s到各顶点的最短路径上的前驱。如果顶点不可达,则最短路径为INT_MAX。
阅读全文