用c++中的list帮我实现dijkstra算法
时间: 2024-04-23 20:16:26 浏览: 10
下面是使用C语言中的list实现Dijkstra算法的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>
#include <string.h>
#define MAX_VERTICES 1000
#define INF INT_MAX
typedef struct Edge {
int dest;
int weight;
struct Edge* next;
} Edge;
typedef struct Vertex {
Edge* head;
int dist;
bool visited;
int prev;
} Vertex;
typedef struct Graph {
Vertex vertices[MAX_VERTICES];
int num_vertices;
} Graph;
typedef struct List {
int value;
struct List* next;
} List;
typedef struct Queue {
List* front;
List* rear;
} Queue;
void init_queue(Queue* q) {
q->front = q->rear = NULL;
}
bool is_queue_empty(Queue* q) {
return q->front == NULL;
}
void enqueue(Queue* q, int value) {
List* new_node = (List*)malloc(sizeof(List));
new_node->value = value;
new_node->next = NULL;
if (is_queue_empty(q)) {
q->front = q->rear = new_node;
} else {
q->rear->next = new_node;
q->rear = new_node;
}
}
int dequeue(Queue* q) {
if (is_queue_empty(q)) {
return -1;
}
List* temp = q->front;
int value = temp->value;
q->front = q->front->next;
if (q->front == NULL) {
q->rear = NULL;
}
free(temp);
return value;
}
void init_graph(Graph* g) {
g->num_vertices = 0;
for (int i = 0; i < MAX_VERTICES; i++) {
g->vertices[i].head = NULL;
g->vertices[i].dist = INF;
g->vertices[i].visited = false;
g->vertices[i].prev = -1;
}
}
void add_edge(Graph* g, int src, int dest, int weight) {
Edge* new_edge = (Edge*)malloc(sizeof(Edge));
new_edge->dest = dest;
new_edge->weight = weight;
new_edge->next = g->vertices[src].head;
g->vertices[src].head = new_edge;
}
void dijkstra(Graph* g, int src) {
g->vertices[src].dist = 0;
Queue q;
init_queue(&q);
enqueue(&q, src);
while (!is_queue_empty(&q)) {
int u = dequeue(&q);
g->vertices[u].visited = true;
Edge* edge = g->vertices[u].head;
while (edge != NULL) {
int v = edge->dest;
int weight = edge->weight;
if (!g->vertices[v].visited && g->vertices[u].dist + weight < g->vertices[v].dist) {
g->vertices[v].dist = g->vertices[u].dist + weight;
g->vertices[v].prev = u;
enqueue(&q, v);
}
edge = edge->next;
}
}
}
void print_shortest_path(Graph* g, int src, int dest) {
if (g->vertices[dest].prev == -1) {
printf("There is no path from %d to %d\n", src, dest);
return;
}
List* path = NULL;
int current = dest;
while (current != src) {
List* new_node = (List*)malloc(sizeof(List));
new_node->value = current;
new_node->next = path;
path = new_node;
current = g->vertices[current].prev;
}
printf("Shortest path from %d to %d: %d", src, dest, src);
while (path != NULL) {
printf(" -> %d", path->value);
path = path->next;
}
printf("\n");
}
int main() {
Graph g;
init_graph(&g);
g.num_vertices = 6;
add_edge(&g, 0, 1, 5);
add_edge(&g, 0, 2, 1);
add_edge(&g, 1, 2, 2);
add_edge(&g, 1, 3, 3);
add_edge(&g, 2, 3, 7);
add_edge(&g, 2, 4, 4);
add_edge(&g, 3, 4, 3);
add_edge(&g, 3, 5, 2);
add_edge(&g, 4, 5, 6);
dijkstra(&g, 0);
print_shortest_path(&g, 0, 5);
return 0;
}
```
在上面的代码中,我们使用了一个辅助的List结构体来实现队列,而不是使用标准库中的队列。我们首先定义了一个List结构体,代表队列中的一个节点,其中value字段代表节点的值,next字段代表指向队列中下一个节点的指针。然后我们定义了一个Queue结构体,代表队列本身,其中front字段代表队首节点的指针,rear字段代表队尾节点的指针。
在dijkstra函数中,我们使用了一个Queue来存储待访问的节点。我们首先将源节点的距离设为0,并将其加入队列中。然后每次从队列中取出一个节点u,并将其标记为已访问。然后我们遍历u的所有邻居节点v,如果v未被访问过,并且从源节点到v的距离比当前记录的距离更短,则更新v的距离,并将v加入队列中。最后,当队列为空时,我们已经找到了从源节点到所有其他节点的最短路径。
在print_shortest_path函数中,我们从目标节点开始向前遍历,直到到达源节点。我们使用一个List来存储路径中的所有节点,然后反向输出路径即可。
在main函数中,我们创建了一个6个节点的有向图,并使用add_edge函数添加了边。然后我们调用dijkstra函数来计算从源节点0到所有其他节点的最短路径,并使用print_shortest_path函数输出从0到5的最短路径。