算法思想

  ①从一个源点开始,找距离它最近的点顶点v

  ②然后以顶点v为起点,去找v能到达的顶点w,即v的邻居

  比较源点直接到 v的距离和(源点到v的距离+v到w的距离)

  若大于后者则更新源点的到w的开销

  ③然后去掉这个顶点v,去寻找下一个到距离源点最近的顶点重复②

    最后更新完所有顶点


算法思路

  1.用邻接表或者一个二维数组(邻接矩阵)来存储图

  2.设置dist存储到源点的最短距离

     known标记顶点是被处理

     path记录路径(到达该顶点的上一个顶点)

  3.这步的实现和算法思想中描述的一样

  4.递归显示出源点到各个顶点的路径


代码实现

  下面是完整的代码实现,分别用了邻接表和邻接矩阵来存图

  样图如下

  

  邻接矩阵存图
#include <iostream>
#include <cstdlib>

#define Infinity 10000
#define VERSIZE  8
#define notvertex -1

using namespace std;
typedef int  Vertex;

int dist[VERSIZE];//存储各顶点到源点的最短距离
bool S[VERSIZE];//将处理过的顶点设置为true
Vertex path[VERSIZE];//存储到该顶点的上一个顶点

void ReadGraph(int Graph[VERSIZE][VERSIZE], int m)// 边m
{
    ;
    Vertex u, v;
    int weight;
    ; i <= m; i++)
    {
        cout << "请输入第" << i << "条边:";
        cin >> u >> v;
        cout << "请输入边(" << u << "," << v << ")的权重:";
        cin >> weight;
        Graph[u][v] = weight;
    }
}

//在没处理过的顶点里 找出距离源点最近的顶点
Vertex FindMinIndex()
{
    int min = Infinity;
    Vertex min_index = ;
    ; i< VERSIZE; i++)
    {
        if (!S[i] && dist[i]<min)
        {
            min = dist[i];
            min_index = i;
        }
    }
    return min_index;
}
//算法关键
void Dijkstra(int Graph[VERSIZE][VERSIZE], Vertex source)
{
    ;
    // 初始化数组  从顶点为1开始能直接到达source的 初始化dis数组 0代表不可达
    ; i < VERSIZE; i++)
    {
        dist[i] = (Graph[source][i] ==  ? Infinity : Graph[source][i]);
        S[i] = false;
        if (dist[i] != Infinity)
            path[i] = source;
        else
            path[i] = notvertex;
    }

    //源点到自身
    dist[source] = ;
    S[source] = true;

    //循环VERSIZE-1次
    ; count < VERSIZE; count++)
    {
        Vertex u = FindMinIndex();//找出距离源点最近的顶点
        S[u] = true;//标记为已知

        ; v < VERSIZE; v++)
        {
             && !S[i])//u可达v 且 v未知
            {
                if (dist[v] >(Graph[u][v] + dist[u]))
                {
                    dist[v] = Graph[u][v] + dist[u];
                    path[v] = u;
                }
            }
        }
    }
}

void PrintDist(Vertex source)
{
    ;
    printf("Source   vertex Dist\n");
    ; i< VERSIZE; i++)
    {
        if (dist[i] != Infinity)
            printf("%d    ->    %d\t%d\n", source, i, dist[i]);
        else
            printf("%d    ->    %d\tInfinity\n", source, i);

    }
}

//输出路径
void PrintPath(int v)
{
    if (path[v] != notvertex)
    {
        PrintPath(path[v]);
        printf("--->");
    }
    printf("%d", v);
}

int main()
{
     ,j=;
    };
    ; i < VERSIZE; i++)//初始化二维数组
    {
        ; j < VERSIZE; j++)
            Graph[i][j] = ;
    }

    ReadGraph(Graph, );
    Dijkstra(Graph, );//源点是1
    PrintDist();
    printf("源点1顶点7的路径:\n");
    PrintPath();//打印从源点到顶点7的路径
    system("pause");
    ;
}

运行结果

  

  邻接表存图
#include <iostream>
#include <cstdlib>

#define VERSIZE 8
#define NotVertex -1
#define Infinity 100000

using namespace std;

typedef int Vertex;

typedef struct vernode VerNode;//定义顶点结构
typedef struct tablelist Table;//定义邻接表

struct vernode
{
    Vertex ver;
    int weight;//权重
    VerNode * pNext;
};

struct tablelist
{
    VerNode header;
    bool known;
    int dist;
    Vertex path;
}T[VERSIZE];

//初始化标表+读图
void InitTable(Table T[], int n, int m)//顶点数n 边数m
{
    ;
    ; i <= n; i++)//初始化表头
    {
        T[i].header.ver = i;
        T[i].header.weight = ;//到自身的权重为0
        T[i].header.pNext = NULL;
        T[i].dist = Infinity;
        T[i].known = false;
        T[i].path = NotVertex;
    }
    Vertex u, v;//边(u,v)
    ;
    VerNode * ptemp;
    ; i <= m; i++)
    {
        cout << "请输入第" << i << "条边:";
        cin >> u >> v;
        cout << "请输入边(" << u <<","<< v << ")的权重:";
        cin >> wei;
        ptemp = (VerNode*)malloc(sizeof(VerNode));
        ptemp->ver = v;
        ptemp->weight = wei;
        ptemp->pNext = T[u].header.pNext;
        T[u].header.pNext = ptemp;
    }
}

//找出到源点距离最小的顶点
Vertex FindMinIndex(Table T[], int n)
{
    ;
    int min = Infinity;
    Vertex min_index = NotVertex;
    ; i <= n; i++)
    {
        if (!T[i].known && T[i].dist < min)
        {
            min = T[i].dist;
            min_index = i;
        }
    }
    return min_index;
}

//下面是算法关键步骤啦  dijkstra算法
void Dijkstra(Table T[], int n, Vertex source)//source源点 顶点数n
{
    ;
    T[source].dist = ;//源点到源点的距离为0
    T[source].known = true;//源点已知

    //在做循环处理前 还要赋值给能直接到达源点的顶点的dist数据
    VerNode * ptemp;//能直接到达源点的顶点
    ptemp = T[source].header.pNext;
    Vertex w;
    while (ptemp)
    {
        w = ptemp->ver;
        T[w].dist = ptemp->weight;
        T[w].path = source;
        ptemp = ptemp->pNext;
    }

    Vertex v;
    //处理n-1个顶点
    ; i <= n-;i++)
    {
        //找出到源点距离最小的顶点
        v = FindMinIndex(T, n);
        if (v == NotVertex)
            break;
        T[v].known = true;
        ptemp = T[v].header.pNext;//找出顶点V所能到的顶点看是否能跟新他们的dist
        while (ptemp)
        {
            w = ptemp->ver;
            if (!T[w].known && T[w].dist > ptemp->weight + T[v].dist)//进行跟新操作
            {
                T[w].dist = ptemp->weight + T[v].dist;
                T[w].path = v;
            }
            ptemp = ptemp->pNext;
        }
    }
}

//下面输出我们的最短路径吧
void PrintPath(Table T[],Vertex v)
{
    if (T[v].path != NotVertex)
    {
        PrintPath(T, T[v].path);
        cout << " ---> ";
    }
    cout << v;
}

int main()
{
    Vertex v;
    InitTable(T, , );
    Dijkstra(T, , );
    cout << "源点1到各个顶点的最短路径如下:" << endl;
    ; v <= ; v++)
    {
        PrintPath(T, v);
        cout << endl;
    }
    system("pause");
    ;
}

运行结果

需要其他的信息可以根据需要输出

修改补充后的:SakuraOne Dijkstra单源最短路径算法


  THOUGHTS

    算法思想好理解  实现的话也挺好理解  但是关键就是理解的程度

    学习嘛 就是不断重复的过程 对想想就对了还有多动手画画

  

Dijkstra——单源最短路径的更多相关文章

  1. Dijkstra 单源最短路径算法

    Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...

  2. Dijkstra单源最短路径,POJ(2387)

    题目链接:http://poj.org/problem?id=2387 Dijkstra算法: //求某一点(源点)到另一点的最短路,算法其实也和源点到所有点的时间复杂度一样,O(n^2); 图G(V ...

  3. 【模板 && 拓扑】 Dijkstra 单源最短路径算法

    话不多说上代码 链式前向星233 #include<bits/stdc++.h> using namespace std; ,_max=0x3fffffff; //链式前向星 struct ...

  4. Bellman-Ford 单源最短路径算法

    Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...

  5. 单源最短路径算法---Dijkstra

    Dijkstra算法树解决有向图G=(V,E)上带权的单源最短路径问题,但是要求所有边的权值非负. 解题思路: V表示有向图的所有顶点集合,S表示那么一些顶点结合,从源点s到该集合中的顶点的最终最短路 ...

  6. Til the Cows Come Home(poj 2387 Dijkstra算法(单源最短路径))

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32824   Accepted: 11098 Description Bes ...

  7. 单源最短路径——dijkstra算法

    dijkstra算法与prim算法的区别   1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...

  8. 【转】Dijkstra算法(单源最短路径)

    原文:http://www.cnblogs.com/dolphin0520/archive/2011/08/26/2155202.html 单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路 ...

  9. 图论(四)------非负权有向图的单源最短路径问题,Dijkstra算法

    Dijkstra算法解决了有向图G=(V,E)上带权的单源最短路径问题,但要求所有边的权值非负. Dijkstra算法是贪婪算法的一个很好的例子.设置一顶点集合S,从源点s到集合中的顶点的最终最短路径 ...

随机推荐

  1. CentOS 7.6下解决登录MySQL时,ERROR 1045 (28000): Access denied for user root@localhost (using password: YES

    https://blog.csdn.net/sinat_35406909/article/details/79763782

  2. Win7 VS2017编译Blender2.79

    去年在VS2013环境编译过一次,重装系统后换了VS2017,正好刚编译完Godot3.0.2,顺手把Blender也编译了吧. 官方Windows下编译指南 https://wiki.blender ...

  3. linux nfs远程挂载和卸载

    一.nfs远程挂载 1.首先确定服务端(实体挂载节点)的IP 2.通过cat  /etc/hosts 查看服务端的server name 3.mount -t nfs servername:/挂载文件 ...

  4. C语言函数指针与 c#委托和事件对比

    C语言: 函数指针可以节省部分代码量,写类似具有多态的函数,比如要比较最大值,如果不用函数指针就只能写比较某一类型比如int类型的max函数,这个max无法比较string的大小.函数指针的意义就不多 ...

  5. 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP

    不管是app的下载链接还是普通文件的链接在微信内置浏览器或者QQ内置浏览器都会被屏蔽.这是微信对第三方下载域名实施的拦截政策.被拦截了用户在微信内打开就会提示“已停止访问该网页”. 那么当我们遇到这个 ...

  6. Filter的使用(web作业)

    一:什么是过滤器 Filter:Servlet过滤器Fileter是一个小型的web组件,它们通过拦截请求和响应,以便查看.提取或以某种方式操作客户端和服务器之间交换的数据,实现“过滤”的功能.Fil ...

  7. self_vs_default_definee_vs_receiver

    最近在学习ruby的过程遇到很多有趣的博客,随记录学习,这篇学习笔记摘自http://yugui.jp/articles/846 #self ruby中self无处不在,或是显示的调用或是隐含调用,方 ...

  8. bzoj4568(合并线性基+倍增)

    裸题练习模板 #include<iostream> #include<cstring> #include<cmath> #include<cstdio> ...

  9. Android 极光推送造成IM服务绑定失败bug

    由于极光推送对8.0的支持问题,升级到了最新版本的极光推送.但是最新版本的极光推送,默认将推送服务设置到了新的进程里面,由此引发 Android 极光推送多进程造成的application运行两次 和 ...

  10. CSS中清除浮动的作用以及如何清除浮动

    1.什么是浮动,浮动的作用 “浮动”从字面上来理解就是“悬浮移动.非固定”的意思.块级元素(div.table.span…)是以垂直方向排列,而在前端界面中往往要使用水平布局块级元素使界面更美观.这就 ...