运用Dijkstra算法求得单源最短路径C/C++

额…,最近博客有一段时间没有更新了,本来打算每周两篇的打算被打断了,不断的意识到坚持一件事长久的做下去是多么的不易,当然也不是说上周什么事情都没有做,只是计算机图形学的作业确实是花了一段时间,虽然最终的效果可能没有那么理想,但确实是自己想要做好的一件事,所以觉得花的时间也是值得的,学一些新的技术固然不错,但个人觉得计算机系的必须要有着坚实的基础,所以数据结构与算法一定是我坚持的方向,好了,先展示下我作业的效果再开始正题吧…
这里写图片描述

一、 算法描述
Dijistra主要用于求得单源最短路径,对带权有向图G = (V,E),源点v0属于V,设置两个顶点集合S和T = V – S,集合S中存放已找到最短路径的顶点,集合T存放当前还未找到最短路径的顶点。初始状态时,集合S中只包含源点v0,然后不断从集合T中选取到顶点v0路径长度最短的顶点u加入集合S中,集合S每加入一个新的顶点u,都要修改顶点v0到集合T中剩余顶点的最短路径长度值,集合T中各顶点新的最短路径长度值为原来的最短路径长度值与顶点u的最短路径长度值加上u到改顶点的路径长度中的较小值。此过程不断重复,直到集合T的顶点全部加入到S中为止。

二、 算法过程
这里写图片描述
三、算法实现

/*
 *Dijkstra算法求得单源最短路径,运用邻接矩阵进行图的储存
 */
#include<stdio.h>
#include<malloc.h>
#define MaxVertexNum 100
#define MAX 9999
typedef char VertexType ;
typedef int EdgeType ;
/*
 *定义图的存储结构
 */
typedef struct
{
    VertexType  vexs[MaxVertexNum][3] ; //定义顶点表
    EdgeType    edges[MaxVertexNum][MaxVertexNum] ; //定义边表
    int n , e ; //定义顶点数与边数
} MGraph ;
/*
 *创建栈,保存路径
 */
typedef struct
{
    VertexType way[MaxVertexNum][3] ;
    int top ;
} Stack ;
/*
 *构建图邻接矩阵
 */
void CreateMGraph(MGraph *G)
{
    int i , j , k , w ;
     printf("请输入定点数与边数(输入格式为:顶点数,边数):") ;
     scanf("%d,%d" , &G->n , &G->e) ;
     printf("请输入顶点信息(输入格式为:顶点号<CR>):\n") ;
     for(i = 0 ; i < G->n ; i++)
     {
         scanf("%s" , G->vexs[i]) ;
     }
     //初始化邻接矩阵
     for(i = 0 ; i < G->n ; i++)
     {
         for(j = 0 ; j < G->n ; j++)
         {
             G->edges[i][j] = MAX ;
         }
     }
     printf("请输入每条边对应的两个顶点序号以及权值(输入格式为:i,j,w):\n") ;
     for(k = 0 ; k < G->e ; k++)
     {
         scanf("%d,%d,%d" , &i , &j , &w) ;
         G->edges[i][j] = w ;
     }
     for(i = 0 ; i < G->n ; i++)
     {
         for(j = 0 ; j < G->n ; j++)
         {
             printf("%04d " , G->edges[i][j]) ;
         }
         printf("\n") ;
     }
}
int finall[MaxVertexNum] ; //定义全局变量,记录顶点是否已求出最短路径
/*
 *求得单源最短路径算法,即Dijkstra算法
 *G为邻接矩阵 , v0为源点 , P为v0到各顶点v的路径 , D为最短路径长度
 */
void ShortestPath_1(MGraph G , int v0 , Stack *sw , int *D)
{
    int v , w , i ,  j , min  , k ;
    for(w = 0 ; w < G.n ; w++)
    {
        sw[w].top = -1 ; //将路径置空
    }
    for(v = 0 ; v < G.n ; v++)
    {
        finall[v] = 0 ;
        D[v] = G.edges[v0][v] ;
        if(D[v]<MAX)
        {
            //对该点当前最短路径进行初始化
           sw[v].top++;
           for(k = 0 ; k < 3 ; k++)
           {
               sw[v].way[sw[v].top][k] = G.vexs[v0][k];
           }
           sw[v].top++;
           for(k = 0 ; k < 3 ; k++)
           {
               sw[v].way[sw[v].top][k] = G.vexs[v][k];
           }
        }
    }
    D[v0] = 0 ;
    finall[v0] = 1 ;
    for(i = 1 ; i < G.n ; i++)
    {
       min = MAX ;
       //在每次循环中找到当前路径最短的点
       for(w = 0 ; w < G.n ; w++)
       {
           if(!finall[w])
           {
               if(D[w] < min)
               {
                   v = w ;
                   min = D[w] ;
               }
           }
       }
       finall[v] = 1 ;
       for(w = 0 ; w < G.n ; w++)
       {
           if(!finall[w]&&((min + G.edges[v][w]) < D[w]))
           {
                // 修改路径与路径长度
                sw[w].top = sw[v].top ;
                for(j = 0 ; j <= sw[v].top ; j++)
                {
                    for(k = 0 ; k < 3 ; k++)
                    {
                        sw[w].way[j][k] = sw[v].way[j][k] ;
                    }
                }
                sw[w].top++ ;
                for(k = 0 ; k < 3 ; k++)
                {
                    sw[w].way[j][k] = G.vexs[w][k];
                }
               D[w] = min + G.edges[v][w] ;
           }
       }
    }
}
/*
 *测试代码
 */
void main()
{
    MGraph *G ;
    Stack w[MaxVertexNum] ;
    int i , j ;
    int P[MaxVertexNum][MaxVertexNum] , D[MaxVertexNum] ;
    G = (MGraph*)malloc(sizeof(MGraph)) ;
    CreateMGraph(G) ;
    ShortestPath_1(*G , 0 , w , D) ;
    //对最短路径与最短路径长度进行输出
    for(i = 0 ; i < G->n ; i++)
    {
        if(D[i] < MAX)
        {
            for(j = 0 ; j <= w[i].top ; j++)
            {
                printf("%s->" , w[i].way[j]) ;
            }
            printf("---%d \n" , D[i]) ;
        }
    }
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值