Dijkstra算法(邻接表实现)

Dijkstra算法是求最短路径的经典算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。 

Dijkstra算法采用的是贪心算法的策略,也正是因为Dijkstra这种贪心的策略,导致了其在处理负权路上的无解,因此,使用Dijkstra算法的一大前提便是:

所处理的图中不能有负权边;

算法的基本思想是:每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径。

其基本步骤如下:

1、将所有顶点分为两部分:已知最短路程的顶点集合P和未知最短路程的顶点集合Q。用vis[i]表示,如果vis[i]=1则表示这个顶点在集合P中,反之顶点在集合Q中。
2、设置源点s到自己的最短路径为0。其余按照实际情况进行设置。
3、在集合Q的所有定点中选择一个离源点s最近的顶点加入到集合P。并考察所有以点u为起点的边,对每一条边进行松弛操作。
4、重复第三步,如果集合Q为空,算法结束。最终dis数组中的值就是源点到所有顶点的最短路径。

void Graph::Dijkstra(string begin)
{
    if(pointnum==0)
    {
        printf("don't have the graph\n");
        return;
    }
    memset(dis,inf, sizeof(dis));
    initvis();
    int index = mmp[begin],u;
    ArcNode* p = point[index].firstarc;
    while(p)
    {
        dis[mmp[p->name]]=p->wigth;
        p=p->next;
    }
    vis[index]=1;
    dis[index]=0;
    for(int i=0;i<pointnum-1;i++)
    {
        int minn=inf;
        for(int j=0;j<pointnum;j++)
        {
            if(!vis[j]&&dis[j]<minn)
            {
                minn=dis[j];
                u=j;
            }
        }
        //printf("u=%d\n",u);
        vis[u]=1;
        p=point[u].firstarc;
        while(p)
        {
            if(dis[mmp[p->name]]>dis[u]+p->wigth)
                dis[mmp[p->name]]=dis[u]+p->wigth;
            p=p->next;
        }
    }
    cout<<"Dijkstra:"<<endl;
    for(int i=0;i<pointnum;i++)
    {
        cout<<"from "<<begin<<" to "<<point[i].name<<" the shortest road is:";
        printf("  %d\n",dis[i]);
    }
}

 

下面是使用邻接表实现Dijkstra算法的C语言代码: ```c #include <stdio.h> #include <stdlib.h> #include <limits.h> #define MAX_VERTEX_NUM 100 // 最大顶点数 #define INF INT_MAX // 无穷大 // 边的结构体 typedef struct Edge { int dest; // 目标顶点编号 int weight; // 权重 struct Edge *next; // 下一条边指针 } Edge; // 邻接表中顶点的结构体 typedef struct Vertex { Edge *head; // 第一条边 } Vertex; // 的结构体 typedef struct Graph { Vertex vertices[MAX_VERTEX_NUM]; // 顶点数组 int vertex_num; // 顶点数 } Graph; // 初始化 void init_graph(Graph *graph, int vertex_num) { graph->vertex_num = vertex_num; for (int i = 0; i < vertex_num; i++) { graph->vertices[i].head = NULL; } } // 添加边 void add_edge(Graph *graph, int src, int dest, int weight) { Edge *edge = (Edge *) malloc(sizeof(Edge)); edge->dest = dest; edge->weight = weight; edge->next = graph->vertices[src].head; graph->vertices[src].head = edge; } // Dijkstra算法 void dijkstra(Graph *graph, int start, int *dist, int *prev) { int visited[MAX_VERTEX_NUM] = {0}; // 是否已经访问 for (int i = 0; i < graph->vertex_num; i++) { dist[i] = INF; // 到各个顶点的距离都设置为无穷大 prev[i] = -1; // 各个顶点的前驱顶点都设置为-1 } dist[start] = 0; // 起点到自身的距离为0 for (int i = 0; i < graph->vertex_num; i++) { int min_dist = INF; int u = -1; // 找到未访问顶点中距离最近的顶点 for (int j = 0; j < graph->vertex_num; j++) { if (!visited[j] && dist[j] < min_dist) { min_dist = dist[j]; u = j; } } if (u == -1) { break; } visited[u] = 1; // 标记为已访问 // 更新与顶点u相邻的顶点的距离 for (Edge *edge = graph->vertices[u].head; edge != NULL; edge = edge->next) { int v = edge->dest; int w = edge->weight; if (!visited[v] && dist[u] + w < dist[v]) { dist[v] = dist[u] + w; prev[v] = u; } } } } // 打印最短路径 void print_path(Graph *graph, int start, int end, int *prev) { if (start == end) { printf("%d", start); } else if (prev[end] == -1) { printf("无路径"); } else { print_path(graph, start, prev[end], prev); printf("->%d", end); } } int main() { Graph graph; init_graph(&graph, 5); add_edge(&graph, 0, 1, 10); add_edge(&graph, 0, 3, 30); add_edge(&graph, 0, 4, 100); add_edge(&graph, 1, 2, 50); add_edge(&graph, 2, 4, 10); add_edge(&graph, 3, 2, 20); add_edge(&graph, 3, 4, 60); int dist[MAX_VERTEX_NUM]; int prev[MAX_VERTEX_NUM]; dijkstra(&graph, 0, dist, prev); for (int i = 1; i < graph.vertex_num; i++) { printf("0到%d的最短距离为%d,路径为", i, dist[i]); print_path(&graph, 0, i, prev); printf("\n"); } return 0; } ``` 该代码使用邻接表存储实现Dijkstra算法,可以求解任意两个顶点之间的最短路径
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值