Dijkstra算法模拟讲解
dijkstra算法,是一个求单源最短路径算法
其算法的特点为:
层层逼进,有点类似宽度搜索的感觉
其需要的数据结构为:
int map[N][N] 所有点之间的权表
int dis[N]
所有点到源点的最短距离
int prev[N] 存储每个点的前一个经过的点,用于输出路径
int used[N] 用于存储已经求出最短路径的点
则总的点减去used中的点,为还没有找出最短路径的点
初始化时:map为实际存储的权,如果某一边没有,则设置为无穷大INF,自身设置0
dis为源点到该点的距离,如果没有,也设置为无穷大INF
prev,如果与源点相邻,则设置为源点,否则为0
used 除了源点外,其余全为0
第一次比较源点到其相邻的点,找出最短距离的点k,将其加入used[k] = 1;
比较与k相邻的点j到源点的距离,如果比(dis[k] + map[k][j])源点到k + k
到j点的距离大,那么更新dis[j] = dis[k] + map[k][j],并记录prev[j] = k,
表示j的前一个经过的点为k,再重复寻找其余的点到源点的最短距离,再把找到
的点加入used中,直到全部节点都加入used中时,最短路径已完毕。
具体实现如下:
/*
Filename:dijkstra.cpp
Author: xiaobing
E-mail: xiaobingzhang29@gmail.com
Date: 2013-08-30
*/
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<string.h>
#include<stack>
#define N 50
#define M 50
#define INF 0xfffffff
using namespace std;
/*
*dijkstra算法,是一个求单源最短路径算法
其算法的特点为:
层层逼进,有点类似宽度搜索的感觉
其需要的数据结构为:
int map[N][N] 所有点之间的权表
int dis[N] 所有点到源点的最短距离
int prev[N] 存储每个点的前一个经过的点,用于输出路径
int used[N] 用于存储已经求出最短路径的点
则总的点减去used中的点,为还没有找出最短路径的点
初始化时:map为实际存储的权,如果某一边没有,则设置为无穷大INF,自身设置0
dis为源点到该点的距离,如果没有,也设置为无穷大INF
prev,如果与源点相邻,则设置为源点,否则为0
used 除了源点外,其余全为0
第一次比较源点到其相邻的点,找出最短距离的点k,将其加入used[k] = 1;
比较与k相邻的点j到源点的距离,如果比(dis[k] + map[k][j])源点到k + k
到j点的距离大,那么更新dis[j] = dis[k] + map[k][j],并记录prev[j] = k,
表示j的前一个经过的点为k,再重复寻找其余的点到源点的最短距离,再把找到
的点加入used中,直到全部节点都加入used中时,最短路径已完毕。 */ /*
*dijkstra算法
*@node 总共的节点数
*@from 源点
*@map 点与点之间的权表
*@dis 源点到该点的最短距离
*@prev 存储当前的前一个经过的点
*/
void dijkstra(int node, int from, int map[][N], int dis[], int prev []){
int i,j,k;
//初始化为所有节点均为求出最短路径
int used[N] = {0};
//第一个点已使用,并且已求出
used[from] = 1;
//初始化源点到其他点的距离
for(i = 1;i <= node;i++){
dis[i] = map[from][i];
//如果源点到该点不可达,那么其前经过的点为0
//相反为from
if(dis[i] == INF || dis[i] == 0){
prev[i] = 0;
} else {
prev[i] = from;
}
}
int min;
//遍历node次,寻找每个点到源点的最短距离
for(i = 1;i <= node;i++){
//初始化为无穷大
min = INF;
//遍历其他没有加入used中的点,并找出最短路径的点k
for(j = 1;j <= node;j++){
if(!used[j] && dis[j] < min){
min = dis[j];
k = j;
}
} //将该点加入used中,表示已求出从源点到该点的最短路径
used[k] = 1; //更新与k相邻的点到源点的距离
//如果经过k点到j的距离更短,那么更新dis[j](从源点到j的距离)
//为源点到k的距离 + k到j的距离,即:dis[k] + map[k][j]
//并更新j的前一个经过的点为k
for(j = 1;j <= node;j++){
if(dis[j] > dis[k] + map[k][j]){
dis[j] = dis[k] + map[k][j];
prev[j] = k;
}
}
}
} //打印二维表
void print(int table[][M], int row, int col){
int i,j;
for(i = 0;i < row;i++){
for(j = 0;j < col;j++){
cout<<table[i][j]<<" ";
} cout<<endl;
}
} //打印路径,由于是一个点储存才是前置节点,可以用栈来存储
//from 为源点
//to 为目的点
//prev 为前置节点路径
void printPath(int from, int to, int prev[]){
stack<int> path;
//把目标点入栈
path.push(to);
//一直找到源点,当然,也可能没有源点,但那个点的前置节点为0
//这里需要防止环路,所以可以用距离来判断,当相等时,就退出了
while(prev[to] != 0){
path.push(prev[to]);
to = prev[to]; }
//如果栈顶节点不是源点,说明从源点到目标点不可达
if(path.top() != from){
cout<<"没有路径"<<endl;
return ;
} cout<<"路径为: "; int flag = 0; //第一次不输出指标
while(!path.empty()){
if(flag)
cout<<"->";
flag = 1;
cout<<path.top();
path.pop();
}
cout<<endl;
}
int main(){
int i, j;
//定义一个权表
int map[N][M];
//初始化map为INF
for(i = 0;i < N;i++){
for(j = 0;j < M;j++){
map[i][j] = INF;
if(i == j){
map[i][j] = 0;
}
}
}
//print(map, N, M);
//node 节点数
//line 边数
//start 源点
int node,line,start;
cin>>node;
cin>>line;
cin>>start; int from, to,len;
//接受数据并初始化map
for(i = 0;i < line;i++){
cin>>from>>to>>len;
map[from][to] = len;
}
cout<<endl;
cout<<"原始数据为:"<<endl;
print(map, node + 1, node + 1);
cout<<endl; //初始时所有的最短路径为0,前置节点为0
int dis[N] = {0};
int prev[N] = {0};
dijkstra(node, start, map, dis, prev);
for(i = 0;i <= node;i++){
cout<<prev[i]<<" ";
}
cout<<endl; cout<<"从节点"<<start<<"到其他节点的最短距离为:"<<endl; for(i = 1;i <= node;i++){
cout<<start<<"--"<<i<<"距离为:"<<dis[i]<<endl;
printPath(start, i, prev);
}
return 0;
}
测试数据为:
5
7
1
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60 原始数据为:
0 268435455 268435455 268435455 268435455 268435455
268435455 0 10 268435455 30 100
268435455 268435455 0 50 268435455 268435455
268435455 268435455 268435455 0 268435455 10
268435455 268435455 268435455 20 0 60
268435455 268435455 268435455 268435455 268435455 0 0 0 1 4 1 3
从节点1到其他节点的最短距离为:
1--1距离为:0
路径为: 1
1--2距离为:10
路径为: 1->2
1--3距离为:50
路径为: 1->4->3
1--4距离为:30
路径为: 1->4
1--5距离为:60
路径为: 1->4->3->5 ===================================== 5
7
5
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60 原始数据为:
0 268435455 268435455 268435455 268435455 268435455
268435455 0 10 268435455 30 100
268435455 268435455 0 50 268435455 268435455
268435455 268435455 268435455 0 268435455 10
268435455 268435455 268435455 20 0 60
268435455 268435455 268435455 268435455 268435455 0 0 0 0 0 0 0
从节点5到其他节点的最短距离为:
5--1距离为:268435455
没有路径
5--2距离为:268435455
没有路径
5--3距离为:268435455
没有路径
5--4距离为:268435455
没有路径
5--5距离为:0
路径为: 5
=====================================
原始数据为:
0 268435455 268435455 268435455 268435455 268435455
268435455 0 40 10 268435455 268435455
268435455 268435455 0 10 30 50
268435455 268435455 80 0 20 40
268435455 268435455 268435455 268435455 0 10
268435455 268435455 268435455 268435455 268435455 0 0 0 0 2 2 4
从节点2到其他节点的最短距离为:
2--1距离为:268435455
没有路径
2--2距离为:0
路径为: 2
2--3距离为:10
路径为: 2->3
2--4距离为:30
路径为: 2->4
2--5距离为:40
路径为: 2->4->5
Dijkstra算法模拟讲解的更多相关文章
- Kruskal算法模拟讲解
Kruskal 算法是一个求最小生成树的算法,即求最小的开销等 算法可以这样,要求得最小生成树,那么n个节点只能包括n-1条边 所以我们应该转换为寻找这最短的n-1条边,因此,可以先对所有的 边进行从 ...
- 三角网格上的寻路算法Part.1—Dijkstra算法
背景 最近在研究中产生了这样的需求:在三角网格(Mesh)表示的地形图上给出两个点,求得这两个点之间的地面距离,这条距离又叫做"测地线距离(Geodesic)".计算三角网格模型表 ...
- 数据结构--Dijkstra算法最清楚的讲解
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径.它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止 ###基本思想 通过Dij ...
- 7-11 社交网络图中结点的“重要性”计算 (30 分)(Dijkstra算法)
题意: 思路:对每个输入的点跑一遍dijkstra算法,然后对这个点到所有点的距离求和按公式输出就可以了. (这次尝试了用数组模拟链表来做最短路问题,刷新了自己对最短路的理解) 这里构造链表的过程我 ...
- [图论]Dijkstra 算法小结
Dijkstra 算法小结 By Wine93 2013.11 1. Dijkstra 算法相关介绍 算法阐述:Dijkstra是解决单源最短路径的算法,它可以在O(n^2)内计算出源点(s)到图中 ...
- Cocos2d-x 地图步行实现1:图论Dijkstra算法
下一节<Cocos2d-x 地图行走的实现2:SPFA算法>: http://blog.csdn.net/stevenkylelee/article/details/38440663 本文 ...
- 单源最短路径问题之dijkstra算法
欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 算法的原理 以源点开始,以源点相连的顶点作为向外延伸的顶点,在所有这些向外延伸的顶 ...
- 最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)
一.主要内容: 介绍图论中两大经典问题:最小生成树问题以及最短路径问题,以及给出解决每个问题的两种不同算法. 其中最小生成树问题可参考以下题目: 题目1012:畅通工程 http://ac.jobdu ...
- (转)最短路算法--Dijkstra算法
转自:http://blog.51cto.com/ahalei/1387799 上周我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最短 ...
随机推荐
- RandomAccessFile浅析
RandomAccessFile类中的write方法有以下的注意事项: 首先write方法每次都写入一个字节 api中write方法如下 public void write(int b) throws ...
- VueJS搭建简单后台管理系统框架 (二) 模拟Ajax数据请求
开发过程中,免不了需要前台与后台的交互,大部分的交互都是通过Ajax请求来完成,在服务端未完成开发时,前端需要有一个可以模拟Ajax请求的服务器. 在NodeJs环境下,通过配置express可访问的 ...
- JS数组操作常用方法
toString():把数组转换成一个字符串 toLocaleString():把数组转换成一个字符串 join():把数组转换成一个用符号连接的字符串 shift():将数组头部的一个元素移出 un ...
- 防抖(Debouncing)和节流(Throttling)
onscoll防抖封装函数 scroll 事件本身会触发页面的重新渲染,同时 scroll 事件的 handler 又会被高频度的触发, 因此事件的 handler 内部不应该有复杂操作,例如 DOM ...
- jira 解决结果配置
jira 的配置比较繁琐,有很多的小细节,使用中出现了各种小问题,总结梳理下 1.解决结果 问题1:编辑了任务后,解决结果变成了已解决 找到编辑任务所对应的界面方案,将解决结果字段从界面配置里移除 问 ...
- hdu 2604Queuing dp+ 矩阵快速幂
题目链接 给一个长度为n的字符串, 每个字符可以使f或m. 问你不包含子串fmf以及fff的字符串数量有多少. 令0表示mm结尾, 1表示mf, 2表示ff, 3表示fm. 那么 f(n+1, 0) ...
- [C#]Windows文件分类器小程序
我平时习惯把各种文件都下载在`下载`文件夹中,时间久了,文件多了,想要找个文件就不那么方便了.于是我就想自己写一个小程序来实现下载文件的自动整理.我想到的文件分类方式是按照文件扩展名分类:把各文件移动 ...
- 点语法、property、self注意
1.点语法(找出不合理的地方)#import <Foundation/Foundation.h>@interface Person : NSObject{ int _age;}- ( ...
- Orchard 源码探索(Module,Theme,Core扩展加载概述)
参考: http://www.orchardch.com/Blog/20120830071458 1. host.Initialize(); private static IOrchardHost H ...
- SQL Server 修改表
alter table 可能用三种方式来完成. 第一种: 只修改元数据. 1.删除一个列. 2.一个行被增加而且空值被认为是所有行的新值. 3.当可变长度的列的长度增加时. 4.不允许为空的列被允许为 ...