C语言实现Dijkstra算法

问题描述

Dijkstra算法是一种用于寻找图中两点之间最短路径的算法。这个算法可以应用在任何有向图和无向图中,只要图的边都有非负权重。

解决方案和代码

以下是使用C语言实现Dijkstra算法的代码,我已经在代码中添加了注释以帮助理解:

#include <stdio.h>
#include <limits.h>

#define V 9

// 用于找到最小距离节点的函数
int minDistance(int dist[], bool sptSet[])
{
    int min = INT_MAX, min_index;

    for (int v = 0; v < V; v++)
        if (sptSet[v] == false && dist[v] <= min)
            min = dist[v], min_index = v;

    return min_index;
}

// 用于打印解决方案的函数
void printSolution(int dist[])
{
    printf("Vertex \t\t Distance from Source\n");
    for (int i = 0; i < V; i++)
        printf("%d \t\t %d\n", i, dist[i]);
}

// 实现Dijkstra算法的函数
void dijkstra(int graph[V][V], int src)
{
    int dist[V]; // 存储源点到其他所有点的最短路径

    bool sptSet[V]; // sptSet[i]为true表示顶点i在最短路径集合中

    // 初始化所有距离为无穷大,sptSet[]为false
    for (int i = 0; i < V; i++)
        dist[i] = INT_MAX, sptSet[i] = false;

    // 源点到自身的距离始终为0
    dist[src] = 0;

    // 找到最短路径的所有顶点
    for (int count = 0; count < V - 1; count++) {
        // 选择当前最小距离顶点
        int u = minDistance(dist, sptSet);

        // 将选定的顶点标记为已处理
        sptSet[u] = true;

        // 更新u的邻接点的距离值
        for (int v = 0; v < V; v++)

            // 更新dist[v]只有当以下条件都满足:
            // 1. v未在sptSet中
            // 2. 通过u存在一个到v的路径
            // 3. 当前dist[u] + dist[u][v]小于当前dist[v]
            if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX
                && dist[u] + graph[u][v] < dist[v])
                dist[v] = dist[u] + graph[u][v];
    }

    // 打印最短路径数组
    printSolution(dist);
}

int main()
{
    // 创建一个示例图
    int graph[V][V] = { { 0, 4, 0, 0, 0, 0, 0, 8, 0 },
                        { 4, 0, 8, 0, 0, 0, 0, 11, 0 },
                        { 0, 8, 0, 7, 0, 4, 0, 0, 2 },
                        { 0, 0, 7, 0, 9, 14, 0, 0, 0 },
                        { 0, 0, 0, 9, 0, 10, 0, 0, 0 },
                        { 0, 0, 4, 14, 10, 0, 2, 0, 0 },
                        { 0, 0, 0, 0, 0, 2, 0, 1, 6 },
                        { 8, 11, 0, 0, 0, 0, 1, 0, 7 },
                        { 0, 0, 2, 0, 0, 0, 6, 7, 0 } };

    // 使用Dijkstra算法找到源点0到所有其他点的最短路径
    dijkstra(graph, 0);

    return 0;
}

运行结果:

总结

Dijkstra算法是一种非常有效的用于解决最短路径问题的算法。它的主要思想是每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其它所有点的最短路径。尽管Dijkstra算法非常有效,但它依赖于图中所有边的权重非负这一假设。如果图中存在负权边,那么我们需要使用更复杂的Bellman-Ford算法。此外,Dijkstra算法并不适用于动态图,因为它会立即丢弃更长的路径。但在许多实际情况下,Dijkstra算法是解决最短路径问题的一个非常好的选择。总的来说,理解和掌握Dijkstra算法,对于深入理解图论和网络路由等领域非常有帮助。

在代码实现方面,我们首先初始化了一个距离数组和一个集合来跟踪已经处理过的顶点。然后,我们使用一个循环来找到所有的最短路径。在每次迭代中,我们首先找到当前未处理的顶点中距离最小的一个,然后更新所有与该顶点相邻的顶点的距离。这个过程会一直持续到我们找到了从源点到所有其他顶点的最短路径。最后,我们打印出了最短路径数组,以便我们可以看到从源点到每个顶点的最短距离。

希望这篇博客能帮助你更好地理解Dijkstra算法和它的C语言实现。如果你有任何问题或者建议,欢迎留言讨论。谢谢!

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dijkstra算法是一种经典的最短路径算法,用于在加权图中寻找单源最短路径。下面是C语言实现Dijkstra算法的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <limits.h> #define MAX_VERTICES 1000 typedef struct Graph { int num_vertices; int matrix[MAX_VERTICES][MAX_VERTICES]; } Graph; Graph* create_graph(int num_vertices) { Graph* graph = (Graph*) malloc(sizeof(Graph)); graph->num_vertices = num_vertices; for (int i = 0; i < num_vertices; i++) { for (int j = 0; j < num_vertices; j++) { graph->matrix[i][j] = 0; } } return graph; } void add_edge(Graph* graph, int src, int dst, int weight) { graph->matrix[src][dst] = weight; } int get_min_distance(int* distances, bool* visited, int num_vertices) { int min_distance = INT_MAX; int min_index = -1; for (int i = 0; i < num_vertices; i++) { if (!visited[i] && distances[i] <= min_distance) { min_distance = distances[i]; min_index = i; } } return min_index; } void dijkstra(Graph* graph, int src, int* distances) { bool visited[MAX_VERTICES] = { false }; for (int i = 0; i < graph->num_vertices; i++) { distances[i] = INT_MAX; } distances[src] = 0; for (int i = 0; i < graph->num_vertices - 1; i++) { int u = get_min_distance(distances, visited, graph->num_vertices); visited[u] = true; for (int v = 0; v < graph->num_vertices; v++) { if (!visited[v] && graph->matrix[u][v] && distances[u] != INT_MAX && distances[u] + graph->matrix[u][v] < distances[v]) { distances[v] = distances[u] + graph->matrix[u][v]; } } } } int main() { int num_vertices; scanf("%d", &num_vertices); Graph* graph = create_graph(num_vertices); int num_edges; scanf("%d", &num_edges); for (int i = 0; i < num_edges; i++) { int src, dst, weight; scanf("%d %d %d", &src, &dst, &weight); add_edge(graph, src, dst, weight); } int src; scanf("%d", &src); int distances[MAX_VERTICES]; dijkstra(graph, src, distances); for (int i = 0; i < num_vertices; i++) { printf("Shortest distance from %d to %d is %d\n", src, i, distances[i]); } return 0; } ``` 输入格式为: ``` <num_vertices> <num_edges> <src> <dst> <weight> ... ``` 其中 `<num_vertices>` 表示图中的顶点数, `<num_edges>` 表示边数,每行输入一个边,包括源顶点、目标顶点和权重。最后一行输入源顶点。输出为源顶点到所有顶点的最短距离。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值