一、Dijkstra算法(贪心地求最短距离的算法)

  在此算法中,我按照自己的理解去命名,理解起来会轻松一些。

  

#define MAXSIZE 100
#define UNVISITED 0
#define VISITED 1
#define INFINITY 66666

typedef struct tool {
    int visited[MAXSIZE];
    /*是否已访问的数组,visited[i]表示顶点i已经访问,也就是到顶点i的最短距离已求出*/
    int known_shortest_distance[MAXSIZE];
    /*已知的最短距离数组。known_shortest_distance[i]代表从V0到Vi的最短距离*/
    int previous_vertex[MAXSIZE];
    /*previous_vertex[i]=j,代表:在从V0到Vi的最短路径上,顶点i的前一个顶点是顶点j*/
} Tool;

typedef struct gragh {
    int num_of_vertexes;
    int adjacent_matrix[MAXSIZE][MAXSIZE];
} Gragh;

void init_tool(Gragh g, Tool &t) {
    ;
    ; i < g.num_of_vertexes; i++) {
        t.visited[i] = UNVISITED;
        t.known_shortest_distance[i] = g.adjacent_matrix[][i];
        t.previous_vertex[i] = ;
    }
}

void dijstra_shortest_distance(Gragh g, Tool &t) {
    int i, j, x; //循环变量
    int min_distance, x_index;
    /*min_distance存储的是当前已知的最短距离数组中从V0到Vx最小的距离;
    x_index存储的Vx的下标*/
    init_tool(g, t);
    ; i < g.num_of_vertexes; i++) {
        min_distance = INFINITY;
        ; x < g.num_of_vertexes; x++) {
            if(!t.visited[x] && t.known_shortest_distance[x] < min_distance) {
                min_distance = t.known_shortest_distance[x];
                x_index = x;
            }
        }
        /*通过上面一个循环,最短距离数组中的最小值就是min_distance;
        该顶点的下标就是x_index;
        在当前没有访问且以V0为起点距离最短的顶点中,
        这个点的下标就是x_index.*/
        t.visited[x_index] = VISITED;

        ; j < g.num_of_vertexes; j++) {
            if(!t.visited[j] && (min_distance + g.adjacent_matrix[x_index][j] < t.known_shortest_distance[j])) {
                t.known_shortest_distance[j] = min_distance + g.adjacent_matrix[x_index][j];
                t.previous_vertex[j] = x_index;
            }
        }
    }

}

如果要求任意两点之间的最短距离:只需在外层加一层循环,把最短距离数组和previous_vertex数组变成二维数组即可。

输出从V0到Vi的最短距离和完整路径:

#include<stack>
void print_path(Tool &t, int dest) {
    int i = dest;
    stack<int> s;
    cout << "从V0到V" << i << "的最短距离:" << t.known_shortest_distance[i] << endl;
    ) {
        s.push(t.previous_vertex[i]);
        i = t.previous_vertex[i];
    }
    cout << "从V0到V" << i << "的路径:";
    cout<<"V0";
    while(!s.empty()) {
        cout << "->V" << s.top();
        s.pop();
    }
    cout << "->V" << dest;
}

一、Floyd算法(不管三七二十一,先把整个图中任意两点的最短距离求出再说)

  核心思想:对图中任意两个顶点(即下面代码中的j和k),如果能在其他顶点中(也就是下面代码中的i,在原始版本中,i和j,k可以相同)找到一个顶点i,使得顶点j到顶点i的距离加上顶点i的距离到顶点k的距离比直接从顶点j到顶点k的距离短,那么,就修改顶点j到顶点k的距离。

typedef struct floyd_tool {
    int known_shortest_distance[MAXSIZE][MAXSIZE];
    /*已知的最短距离数组。known_shortest_distance[i][j]代表从Vi到Vj的最短距离*/
    int path_matrix[MAXSIZE][MAXSIZE];
    /*path_matrix[i][j]=k,代表:在从Vi到Vj的最短路径上,要经过顶点k;
    用k代替i,直到path_matrix[k][j]=j*/
} FloydTool;

void init_floyd_tool(FloydTool &ft, Gragh g) {
    ; i < g.num_of_vertexes; i++) {
        ; j < g.num_of_vertexes; j++) {
            ft.known_shortest_distance[i][j] = g.adjacent_matrix[i][j];
            ft.path_matrix[i][j] = j;
        }
    }
}

void floyd_shortest_distance(Gragh g,FloydTool &ft) {
    init_floyd_tool(ft,g);
    ;i < g.num_of_vertexes; i++){
        ;j < g.num_of_vertexes;j++){
            ;k < g.num_of_vertexes;k++){
                if(ft.known_shortest_distance[j][k] >
                   ft.known_shortest_distance[j][i] + ft.known_shortest_distance[i][k]){
                    ft.known_shortest_distance[j][k] =
                    ft.known_shortest_distance[j][i] + ft.known_shortest_distance[i][k];
                    ft.path_matrix[j][k] = ft.path_matrix[j][i];
                   }
            }
        }
    }
}

改进版:

改进依据:由上面初始版本的思想可知,对于任意两个顶点j和顶点k,如果顶点j和顶点i是同一个,那么,最里面一层的比较相当于是D和0+D在比,显然,这是没必要的。或者,如果j和i不相等,但是i不是j的邻接点,那么j到i的距离就是“无穷大”,很显然,通过这个桥梁i是不可能缩短j到k的距离的。所以,有了第一个if;同理,第二个if也是这么来的。然后,初始版本中,最里面两层循环的循环变量都是从0开始的,但是因为我们考虑的是无向图,j到k的距离和k到j的距离是一样的,所以,我在改进版本中减去了重复求k到j的距离。

void floyd_shortest_distance(Gragh g,FloydTool &ft) {
    init_floyd_tool(ft,g);
    ;i < g.num_of_vertexes; i++){
        ;j < g.num_of_vertexes;j++){
            if(j == i || ft.known_shortest_distance[j][i] == INFINITY)continue;
            for(int k = j + 1;k < g.num_of_vertexes;k++){
                if(k == i || ft.known_shortest_distance[k][i] == INFINITY)continue;
                if(ft.known_shortest_distance[j][k] >
                   ft.known_shortest_distance[j][i] + ft.known_shortest_distance[i][k]){
                    ft.known_shortest_distance[j][k] =
                    ft.known_shortest_distance[j][i] + ft.known_shortest_distance[i][k];
                    ft.path_matrix[j][k] = ft.path_matrix[j][i];
                   }
            }
        }
    }
}

输出最短距离和完整路径:

void print_path(FloydTool &ft,int orig,int dest) {
    cout << "从V"<<orig<<"到V"<<dest<< "的最短距离:" << ft.known_shortest_distance[orig][dest] << endl;
    cout << "从V"<<orig<<"到V"<<dest<<"的路径:";
    cout<<"V"<<orig;
    while(ft.path_matrix[orig][dest] != dest){
        cout<<"->V"<<ft.path_matrix[orig][dest];
        orig = ft.path_matrix[orig][dest];
    }
    cout << "->V" << dest;
}

数据结构——图——最短路径D&F算法的更多相关文章

  1. 算法学习记录-图——最短路径之Dijkstra算法

    在网图中,最短路径的概论: 两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点. 维基百科上面的解释: 这个算法是通过为每个顶点 v 保留目前为止所找到的从 ...

  2. 算法与数据结构(六) 迪杰斯特拉算法的最短路径(Swift版)

    上篇博客我们详细的介绍了两种经典的最小生成树的算法,本篇博客我们就来详细的讲一下最短路径的经典算法----迪杰斯特拉算法.首先我们先聊一下什么是最短路径,这个还是比较好理解的.比如我要从北京到济南,而 ...

  3. 数据结构与算法--最短路径之Bellman算法、SPFA算法

    数据结构与算法--最短路径之Bellman算法.SPFA算法 除了Floyd算法,另外一个使用广泛且可以处理负权边的是Bellman-Ford算法. Bellman-Ford算法 假设某个图有V个顶点 ...

  4. 数据结构与算法--最短路径之Floyd算法

    数据结构与算法--最短路径之Floyd算法 我们知道Dijkstra算法只能解决单源最短路径问题,且要求边上的权重都是非负的.有没有办法解决任意起点到任意顶点的最短路径问题呢?如果用Dijkstra算 ...

  5. 数据结构与算法--最短路径之Dijkstra算法

    数据结构与算法--最短路径之Dijkstra算法 加权图中,我们很可能关心这样一个问题:从一个顶点到另一个顶点成本最小的路径.比如从成都到北京,途中还有好多城市,如何规划路线,能使总路程最小:或者我们 ...

  6. <数据结构>图的最短路径问题

    目录 最短路径问题 Dijstra算法:中介点优化 基本步骤 伪代码 在实现过程中的关键问题 代码实现 邻接矩阵版 邻接表版 时间复杂度:O(VlogV+E) 算法存在的问题:存在负权边时会失效 Be ...

  7. 【算法设计与分析基础】25、单起点最短路径的dijkstra算法

    首先看看这换个数据图 邻接矩阵 dijkstra算法的寻找最短路径的核心就是对于这个节点的数据结构的设计 1.节点中保存有已经加入最短路径的集合中到当前节点的最短路径的节点 2.从起点经过或者不经过 ...

  8. JavaScript数据结构——图的实现

    在计算机科学中,图是一种网络结构的抽象模型,它是一组由边连接的顶点组成.一个图G = (V, E)由以下元素组成: V:一组顶点 E:一组边,连接V中的顶点 下图表示了一个图的结构: 在介绍如何用Ja ...

  9. 数据结构C语言版 弗洛伊德算法实现

    /* 数据结构C语言版 弗洛伊德算法  P191 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h>#include <limits.h> # ...

随机推荐

  1. ffmpeg命令学习

    1.组成 程序:ffmpeg.ffplay.ffprobe.ffserverffmpeg:转码程序ffplay:播放程序ffserver:服务器程序 库:libavcodec.libavdevice. ...

  2. MIPI DSI 和 D-PHY 初始化序列

    MIPI DSI 和 D-PHY 初始化序列 -- 深圳 南山平山村 曾剑锋 参考文档: i.MX 6Dual/6Quad Multimedia Applications Processor Refe ...

  3. ecshop 设置管理员

    <?php define('IN_ECS', true); require(dirname(__FILE__) . '/includes/init.php'); $admin_name=trim ...

  4. web.xml 中的listener、 filter、servlet 加载顺序

    在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是 ...

  5. mysql添加用户和用户权限

    Mysql添加用户使用可以对mysql数据库用户表有操作权限的用户名登陆mysqlinsert into user(Host,User,Password) values('%','name','pas ...

  6. php 采集程序 宋正河

    本程序主要是通过php采集网页信息,程序自动存储采集进度,采用phpquery简化元素节点匹配,采集到的内容直接入库 你要做的只是写好采集语法,本程序适合有一定php基础的人使用!当然你也可以进行修改 ...

  7. iframe根据子页面自动调整大小

    //iframe高度自适应 function IFrameReSize(iframename) { var pTar = document.getElementById(iframename); if ...

  8. grails中报Cannot create a session after the response has been committed异常的解决办法

    在grails中,我们在layouts\main.gsp中使用类似如下的代码来判断当前用户处于登录状态时显示相关的登录信息: <g:if test="${session.users}& ...

  9. 数往知来 ASP.NET 模拟服务器:服务端_静态页面_动态页面的响应<十七>

      一.客户端是怎么看到我们的网页的呢/ 在浏览器端,如果用汉语请求的是一普通的HTML网页,呢么我们的IIS服务器, 接收到请求以后,那么从IIS服务器所在的电脑区查找该HTML网页, 找到以后将该 ...

  10. C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法----细节决定成败 (sort用法)

    C++中cin.cin.get().cin.getline().getline().gets()等函数的用法 学C++的时候,这几个输入函数弄的有点迷糊:这里做个小结,为了自己复习,也希望对后来者能有 ...