• 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
    


  • 相关阅读:
    windows live sync, mesh, skydrive
    忘记SQL SERVER密码的解决
    处理ObjectDataSource调用中DAL层中的异常
    C#中获取应用程序路径的方法(集合)
    datatable复制一行数据到本表
    [Yii Framework] yii中如何在查询的时候使用数据库函数
    [Yii Framework] yii的路由配置
    [Yii Framework] 已经定义的命名空间常量
    [Yii Framework] yii中关于filter
    [Yii Framework] yii中如何不加载layout
  • 原文地址:https://www.cnblogs.com/james1207/p/3292132.html
Copyright © 2020-2023  润新知