最短路径Dijkstra算法的C语言实现

    第一次发博文还请大家多多指教,文章的部分代码源自于网络,但是经过我的整合得以成为一段可以运行的解决最短路径问题的完整代码。并且会附上我自己的图解便于分析讲解。

  本文主要分为两个部分,一是邻接表的创建,二是最短路径问题的实现。将本文中的代码顺序粘贴下来,即可运行。
  在文章的最后有结合实例且比较详细的最短路径算法的执行情况,博主在之前的学习中这部分理解出现了问题,可能其他人在这个地方的理解也会出现偏差,因此我写了结合实例并且较为详细的运算过程。

   以下是关于邻接矩阵的创建
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

#define MAX 10000
#define MAXVEX 100
#define DEBUG

typedef char VertexType;//顶点类型应该由用户自己定义
typedef int EdgeType;

typedef struct
{
    VertexType vertex[MAXVEX];
    EdgeType   adjList[MAXVEX][MAXVEX];
    int numVertexes,numEdges;//记录结点个数,边的个数
}Graph;
void dijkstra(int startPos,int distance[],int path[],Graph *g);                                //求最短路径
void doDijkstra(Graph *g);
char getValue(int i,Graph *g);  //获取某个编号所对应的顶点
int getNum(char ch,Graph *g);   //获取某个结点的编号
int locates(Graph *g,char ch);  //同样是获取某个结点的编号,同上
int getWeight(int a,int b,Graph *g); //获取某条边的权值

http://wenku.baidu.com/link?url=FziBh462uDKGDfZRvGbclA6UtjOGgk4y5N8Jk3vgESMCV7oV0IOG8RMPQQsY_fxM3EwZVrB4C3wy0N6JgJw4bkEQg4UjK28B_dIHreWGTwO 这是一些图常用的英文词汇,便于理解相关语句

int getWeight(int a,int b,Graph *g)
{
    return g->adjList[a][b];
}

下面两个是一样的原谅博主懒得改了

int locates(Graph *g,char ch)
{
    int i=0;
    for(i=0;i<g->numVertexes;i++)
        if(g->vertex[i]==ch)
            break;
    return i;
}
int getNum(char ch,Graph *g)
{
    int i;
    for(i=0;i<g->numVertexes;i++)
        if(g->vertex[i]==ch)
            return i;
}
void createGraph(Graph *g)  //创建一个图
{
    int i,j,k,w;
    printf("Input the number of vertexes and edges.\n");
    scanf("%d,%d",&g->numVertexes,&g->numEdges);//输入图的顶点和边的数目
    for(i=0;i<g->numVertexes;i++)//输入所有顶点
    {
        printf("Please input the vertexes.\n");
        g->vertex[i]=getchar();//循环输入顶点避免回车符号干扰
        while(g->vertex[i]==‘\n‘)
            g->vertex[i]=getchar();
    }
    for(i=0;i<g->numVertexes;i++)//初始化邻接矩阵,将每个值都定为MAX
        for(j=0;j<g->numVertexes;j++)
            g->adjList[i][j]=MAX;
    for(k=0;k<g->numEdges;k++)//输入边(每个边有两个顶点)和权值
    {
        char ch1,ch2;
        printf("Input the edges(vi,vj)coordinate vi ,coordinate vj and weight.\n");
        ch1=getchar();
        while(ch1==‘\n‘)
            ch1=getchar();
        ch2=getchar();
        while(ch2==‘\n‘)
            ch2=getchar();
        scanf("%d",&w);
        int m=-1;
        int n=-1;
        n=locates(g,ch1);
        m=locates(g,ch2);
        g->adjList[m][n]=w;//对邻接矩阵中的边进行赋值
        g->adjList[n][m]=w;
    }
}

void printGraph(Graph *g)//打印邻接矩阵
{
    int i,j;
    for(i=0;i<g->numVertexes;i++)
    {
        for(j=0;j<g->numVertexes;j++)
            printf(" %5d ",g->adjList[i][j]);
        printf("\n");
    }
}
int main()
{
    Graph g;
    createGraph(&g);
    printGraph(&g);
    doDijkstra(&g);//最短路径算法的执行
    printGraph(&g);
    return 0;
}

接下来是最短路径部分源码

void doDijkstra(Graph *g)
{
    char startVertex;
    int *distance,i,*path;
    distance=(int*)malloc(g->numVertexes*sizeof(int));
    path=(int*)malloc(g->numVertexes*sizeof(int));
    printf("We will begin to find the distance from one vertex to the other vertex.\n");
    printf("Please input the starting vertex.\n");
    startVertex=getchar();
    while(startVertex==‘\n‘)
        startVertex=getchar();//输出起始点到其他所有顶点的最短距离
    dijkstra(getNum(startVertex,g),distance,path,g);
    printf("From vertex %c to the other vertexes the shortest distance are.\n",startVertex);
    for(i=0;i<g->numVertexes;i++)
        printf("to vertex %c the distance are: %d\n",getValue(i,g),distance[i]);
    printf("Here is the path.\n");
    for(i=0;i<g->numVertexes;i++)
    {
        if(path[i]!=-1)
            printf("The %c before the vertex is: %c \n",getValue(i,g),getValue(path[i],g));//输出在求最短路径过程中
                       //目标点和路径上它之前的那个点
    }
}

接下来我主要讲讲最短路径算法的核心组成部分

为了便于讲解:首先声明的是我的顶点是a,b,c,d,e,f,g,h其对应的编号分别为1,2,3,4,5,6,7,8.

void dijkstra(int startPos,int distance[],int path[],Graph *g)
{
    int mindis,nextNode,*mark;
    int i=0,j=0;
    mark=(int *)malloc(g->numVertexes*sizeof(int));
    for(i=0;i<g->numVertexes;i++)   //先将与起始点有边连接的点的距离
                                    //初始化为其与初始点的权值
    {
        distance[i]=getWeight(startPos,i,g);
        mark[i]=0;
        if(i!=startPos&&distance[i]<MAX)
            path[i]=startPos;
        else
            path[i]=-1;
    }
    mark[startPos]=1;
    for(i=0;i<g->numVertexes;i++)
    {
        mindis=MAX;
        for(j=0;j<g->numVertexes;j++)//循环1
        {
            if(mark[j]==0&&distance[j]<mindis)
            {
                nextNode=j;
                mindis=distance[j];
            }
        }
        if(mindis==MAX)
            return ;
        mark[nextNode]=1;
        for(j=0;j<g->numVertexes;j++)//循环2
        {
            if(mark[j]==0&&getWeight(nextNode,j,g)<MAX&&getWeight(nextNode,j,g)+distance[nextNode]<distance[j])
            {
                distance[j]=distance[nextNode]+getWeight(nextNode,j,g);
                path[j]=nextNode;
            }
        }
    }
} 

接下来我就逐步执行算法了

a是起始点其编号为0 mark[0]=1,在循环1中找到距离最小点为b,

mark[1]=1.

执行循环2,发现c与b是相连的(权值不是10000)并且点c没被访问过(即mark[2]=0),然后比较a点直接到c点和a->b->c的距离哪个小(由于a->c无权值故设为10000即无穷大),发现a->b->c的距离更小,于是distance[2]=distance[1]+weight(b,c) (注意distance[1]是初始化为a,b边的权值的)

执行循环2

发现d与b是相连的(权值不是10000)并且d没有被访问过,然后比较distance[3]与distance[2]+weight(b,d)大小关系发现distance[3]更小于是就不改变distance[3]的值

由于其他点不满足条件循环结束

执行循环1

编号2满足条件即c点满足条件,mark[2]=1,被标记

执行循环2

发现编号3没有被标记,但是distance[3] < a->b->c->d所以distance[3]的值不改变

继续执行循环2

发现编号4即e点没被标记,且distance[4]=MAX故将distance[4]更新为a->b->c->e

剩下的执行情况类似,就不一一赘述啦。

时间: 2024-10-27 11:38:30

最短路径Dijkstra算法的C语言实现的相关文章

数据结构:单源最短路径--Dijkstra算法

Dijkstra算法 单源最短路径 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离.指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题. Dijkstra算法 求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 算法思想 带权图G=<V,E>,令S为已确定了最短路径顶点的集合,则可用V-S表示剩余未确定最短路径顶点的集合.假设V0是源点,则初始 S={V

有向网络(带权的有向图)的最短路径Dijkstra算法

什么是最短路径? 单源最短路径(所谓单源最短路径就是只指定一个顶点,最短路径是指其他顶点和这个顶点之间的路径的权值的最小值) 什么是最短路径问题? 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离.指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题. 什么是Dijkstra算法? 求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 算法思想 带权图G=<V,

最短路径-Dijkstra算法与Floyd算法

一.最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1    ADE:2   ADCE:3   ABCE:3 ②在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径. AE:100   ADE:90   ADCE:60   ABCE:70 ③单源点最短路径问题 问题描述:给定带权有向图G=(V, E)和源点v∈V,求从v到G中其余各顶点的最短路径. 应用实例--计算机网络传输的问题:怎样找到一种最经济的方式,从一台计算机向网上所有其它计算机发送一条消息. ④每

单源最短路径Dijkstra算法

1.单源最短路径 函数:返回还未被收录顶点中dist最小者 1 Vertex FindMinDist(MGraph Graph, int dist[], int collected[]) 2 { 3 /*返回未被收录顶点中dist最小者*/ 4 Vertex MinV, V; 5 int MinDist = INFINITY; 6 7 8 for (V = 0; V < Graph->Nv; ++V) 9 { 10 if (collected[V] == false && di

单源最短路径 dijkstra算法实现

本文记录一下dijkstra算法的实现,图用邻接矩阵表示,假设图为无向图,并且连通,有向图,不连通图的做法类似. 算法简述: 首先确定"单源"的源,假设是第0个顶点. 维护三个数组dist[], color[], path[],设其下标分别为0-i-n-1: dist[] 表示源点到顶点i的最短距离,在初始化时,如果源点到顶点i有路径,则初始化为路径的权重,否则初始化为INT_MAX: color[] 数组其实表示两个集合,即color[i]值为1的集合表示已经确定最短路径的点的集合,

有向图中单个源点到终点的最短路径--Dijkstra算法与实现

1.Dijkstra算法能够解决有向图中单个源点到另一终点的最短路径问题,它的算法过程如下: 1)用矩阵graph[]N[N](N为图中节点个数)表示带权的有向图G.若图中两个节点vi和vj是连通的,则graph[i][j]表示这两个节点之间边的权值:若两节点vi和vj不是连通的,则graph[i][j] = -1. 2)设S为从某点start_vec开始的最短路径path的终点集合,初始状态时,集合S中只有起始节点start_vec.设从起始节点start_vec到其余节点vi的最短路径长度为

最短路径-Dijkstra算法(转载)

注意:以下代码 只是描述思路,没有测试过!! Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边. 问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到

最短路径—Dijkstra算法

Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边. 问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径.(单源最短路径) 2.算法

单源最短路径——Dijkstra算法学习

每次都以为自己理解了Dijkstra这个算法,但是过没多久又忘记了,这应该是第4.5次重温这个算法了. 这次是看的胡鹏的<地理信息系统>,看完之后突然意识到用数学公式表示算法流程是如此的好理解,堪称完美. 内容摘抄如下: 网络中的最短路径是一条简单路径,即是一条不与自身相交的路径,最短路径搜索的依据:若从S点到T点有一条最短路径,则该路径上的任何点到S的距离都是最短的. Dijkstra算法搜索步骤: 1.对起始点作标记S,且对所有顶点令D(X)=∞,Y=S: 2.对所有未做标记的点按以下公式