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最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最短 ...
随机推荐
- C++中重载、重写(覆盖)和隐藏的区别实例分析
这篇文章主要介绍了C++中重载.重写(覆盖)和隐藏的区别,是C++面向对象程序设计非常重要的概念,需要的朋友可以参考下 本文实例讲述了C++中重载.重写(覆盖)和隐藏的区别,对于C++面向对象程序设计 ...
- 学习C++语言的50条忠告
50条忠告:(其中有几条觉得写的不够贴切,所以删了,发了余下的部分) 1.把C++当成一门新的语言学习: 2.看<Thinking In C++>,不要看<C++变成死相>: ...
- FAQ:Python环境变量配置
Python安装安装成,需要配置环境变量: 默认情况下,在windows下安装python之后,系统并不会自动添加相应的环境变量.此时不能在命令行直接使用python命令. 1. 首先需要在系统中注册 ...
- FAQ:Python中*args和**agrs的区别
python提供了两种特别的方法来定义函数的参数: 1. 位置参数 *args, 把参数收集到一个元组中,作为变量args >>>def show_args(*args): ...
- [笔记]线性回归&梯度下降
一.总述 线性回归算法属于监督学习的一种,主要用于模型为连续函数的数值预测. 过程总得来说就是初步建模后,通过训练集合确定模型参数,得到最终预测函数,此时输入自变量即可得到预测值. 二.基本过程 1. ...
- C++_bool
1 0 #include <iostream> using namespace std; void main() { && || || - && ; std ...
- oracle 快照(snapshot) 管理
----手工创建oracle 快照 BEGIN DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT (); END; / ---删除快照 详细快照信息能够查看视图 ...
- 从零开始学习UNITY3D(GUI篇)
邻近年底,心也有些散乱,加上工作忙了一阵,在达内培训的课程也落下了不少.对unity3d的热度似乎也有点点下降.痛定思痛,又在淘宝上买了写蛮牛网的视频.总之不管是用任何手段都要逼着自己不要浪费了培训的 ...
- Bower前端包管理器
bower 前端包管理器 为什么要用它 一个新的web项目开始,我们总是很自然地去下载需要用到的js类库文件,比如jQuery.随着项目的进展,我们可能又需要Bootstrap3,其中每个框架之间的依 ...
- SQL学习之计算字段的用法与解析
一.计算字段 1.存储在数据库表中的数据一般不是应用程序所需要的格式.大多数情况下,数据表中的数据都需要进行二次处理.下面举几个例子. (1).我们需要一个字段同时显示公司名和公司地址,但这两个信息存 ...