迪杰斯特拉最短路径算法C语言简单实现

前提:途中不能存在负权值

目的:求出图中源点到其他所有顶点的最短路径。

思想:可以理解为一种贪心算法,从单源点出发,层层向外扩展,直到终点。

步骤:

224116_AYUq_3166429.png

实现:这里简单的以一个无向图为例:

edge.txt

0 2 700
0 4 1000
0 7 300
0 5 600
1 2 1000
1 8 500
1 6 1000
2 3 400
2 8 600
3 4 300
3 6 400
4 5 600
5 6 500
6 8 100
7 8 1000

 

C语言实现:

#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#define MAX_VEX 9
#define INFINITY 9999
int g[MAX_VEX][MAX_VEX] = {INFINITY};
void init()
{
        memset(g,INFINITY,sizeof(g));
        FILE * fp = fopen("edge.txt","r");
        if(!fp)
        {
                printf("edge.txt not exists!\n");
                return ;
        }
        while(!feof(fp))
        {
                int l,r,val;
                fscanf(fp,"%d",&l);
                fscanf(fp,"%d",&r);
                fscanf(fp,"%d",&val);
                g[l][r] = val;
                g[r][l] = val;
        }
        int i,j;
        for(i = 0;i<MAX_VEX;i++)
        {
                for(j = 0;j<MAX_VEX;j++)
                {
                        printf("g[%d][%d]=%d ",i,j,g[i][j]);
                }
                printf("\n");
        }
        fclose(fp);
}
//贪心法则
void DIJ(int v0,int dst)
{
        int final[MAX_VEX] = {0};
        int path[MAX_VEX] = {0}; //保存路径 Path[i]表示到i最短路径的上一个节点
        int dis[MAX_VEX] = {0};  //保存v0到i的距离贪心改变
        int n = MAX_VEX;
        int i,k,tmp;
        for(i =0;i<n;i++)
        {
                g[i][i] = 0;
                if(g[v0][i]==0 || g[v0][i] ==INFINITY)
                  path[i] = 0;
                else
                  path[i] = v0;
                dis[i] = g[v0][i];
        }


        for(i=0;i<n;i++)
        {
                int min = INFINITY*2;
                if(i==v0)
                  continue;
                //每次选出一个到源点的最小值
                for(k=0;k<n;k++)
                {
                        if(!final[k] && dis[k] <min)
                        {
                                min = dis[k];
                                tmp = k;
                        }
                }
                final[tmp] = 1;

                //利用已经求出的最小值更新路径 更新其他路径的距离
                for(k=0;k<n;k++)
                {
                        if(!final[k] && min+g[tmp][k] <dis[k])
                        {
                                dis[k] = min +g[tmp][k];
                                path[k] = tmp;
                        }
                }
        }

        //print src to dst path
        //将最短路径保存到trace数组中此处为逆序保存  最后在逆序输出即为正确顺序
        int trace[MAX_VEX];
        int tot= 0;
        trace[tot++] = dst;
        int temp = path[dst];
        while(temp!=v0)

        {
                trace[tot++] = temp;
                temp = path[temp];
        }
        trace[tot] = v0;
        for(k = tot;k>=0;tot--)
        {
                if(trace[tot]==dst)
                {
                        printf("%d\n",dst);
                        break;
                }
                else
                {
                        printf("%d->",trace[tot]);
                }
        }

}

int main()
{
        init();
        DIJ(0,3);
        return 0;
}

算法复杂度 O(n^2)

 

 

转载于:https://my.oschina.net/u/3166429/blog/1341320

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C语言实现Dijkstra算法求解最短路径的示例代码: ```c #include <stdio.h> #include <limits.h> #define V 6 // 顶点数 #define INF INT_MAX // 定义无穷大 // 找到距离最小的顶点 int minDistance(int dist[], int visited[]) { int min = INF, min_index; for (int v = 0; v < V; v++) { if (!visited[v] && dist[v] <= min) { min = dist[v]; min_index = v; } } return min_index; } // 打印最短路径 void printPath(int parent[], int j) { if (parent[j] == -1) return; printPath(parent, parent[j]); printf("%d ", j); } // 打印结果 void printResults(int dist[], int parent[], int src) { printf("Vertex\t Distance\t Path\n"); for (int i = 0; i < V; i++) { printf("%d\t %d\t\t%d ", i, dist[i], src); printPath(parent, i); printf("\n"); } } // Dijkstra算法最短路径 void dijkstra(int graph[V][V], int src) { int dist[V]; // 存储从源点到其他顶点的距离 int visited[V]; // 标记顶点是否已经被访问 int parent[V]; // 存储最短路径的父节点 // 初始化 for (int i = 0; i < V; i++) { dist[i] = INF; visited[i] = 0; parent[i] = -1; } dist[src] = 0; // 求解最短路径 for (int count = 0; count < V-1; count++) { int u = minDistance(dist, visited); visited[u] = 1; for (int v = 0; v < V; v++) { if (!visited[v] && graph[u][v] && dist[u] + graph[u][v] < dist[v]) { parent[v] = u; dist[v] = dist[u] + graph[u][v]; } } } // 打印结果 printResults(dist, parent, src); } int main() { int graph[V][V] = { { 0, 2, 4, 0, 0, 0 }, { 2, 0, 1, 4, 2, 0 }, { 4, 1, 0, 0, 3, 0 }, { 0, 4, 0, 0, 3, 2 }, { 0, 2, 3, 3, 0, 2 }, { 0, 0, 0, 2, 2, 0 } }; dijkstra(graph, 0); return 0; } ``` 上述代码实现了一个6个顶点的图的最短路径求解。其中,graph数组表示图的邻接矩阵,dijkstra函数实现Dijkstra算法,minDistance函数用于找到距离最小的顶点,printPath函数和printResults函数用于打印最短路径的结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值