zoukankan      html  css  js  c++  java
  • 图的单源最短路径:Dijkstra算法实现

            本文介绍的是图的非负权值的单源最短路径问题。问题的提出是,对于有权图D,t提供源点v,要找到从v到其他所有点的最短路径,即单源最短路径问题,在本文中,解决这一问题,是普遍比较熟悉的Dijkstra算法。

            算法核心思想参见维基。简而言之,设集合S存放已经求出了最短路径的点。初始状态S中只有一个点v0,之后每求得v0到vn的最短路径,就会更新v0到所有vn邻接的点的一致的最短路径(不一定是最终的最短路径),如此重复,每次会确定v0到一个点的最短路径,确定好的点加入S中,直至所有点进入S结束。在本文中通过visited这一数组来标记相应点是否已经加入S。

            以下是代码实现,供参考。其中图的相关部分参见C++ 图的实现


    /*
    *单源最短路径:Dijkstra算法
    *----By F8Master
    */
    
    #include "Graphmtx.h"
    #include<stack>
    #include<iostream>
    using namespace std;
    
    #define  DEFAULTPRE '&' //用于标记
    
    
    template<class T,class E>
    void Dijkstra(Graphmtx<T,E> &G, E *dist, T *pre, T &s)//G为存储的图,dist是距离数组,pre是其路径中前一个点,s为源点
    {
    	int numVertex = G.NumberOfVertices();
    	
    	bool *visited = new bool[numVertex];//标志有木有确定最小距离
    
    	for (int i =0;i<numVertex;i++)//初始化
    	{	
    		dist[i] = G.getWeight(G.getVertexPos(s),i);
    		if (dist[i]>0 && dist[i]<INF)
    			pre[i] = s;
    		else 
    			pre[i] = DEFAULTPRE;
    	}
    	pre[G.getVertexPos(s)] = s;
    	for(int i =0;i<numVertex;i++)
    	{
    		visited[i] = false;
    	}
    
    	int n= G.getVertexPos(s);
    	visited[n] = true;
    
    	for(int i=1;i<numVertex;i++)//每次找一个点,要找numVertex-1次
    	{
    		E min = INF;
    		int u = -1;
    		for(int j=0;j<numVertex;j++) //找一个距离最小的点
    		{
    			if(visited[j]==false && dist[j]<min)
    			{
    				u = j;
    				min = dist[j];		
    			}
    		}
    		if(u > 0)
    		{
    			visited[u]=true;
    			for(int k = 0;k<numVertex;k++)
    			{
    				if(visited[k]==false && dist[u]+G.getWeight(u,k)<dist[k])
    				{
    					dist[k] = dist[u]+G.getWeight(u,k);
    					pre[k] = G.getValue(u);
    					
    				}
    			}
    		}		
    	}
    
    }
    
    template<class T,class E >
    void showPath(Graphmtx<T,E> &G,T *pre,T &end,T &start)
    {
    	stack<T> s;
    	if(end!=start)
    	{
    		T v = end;
    		while(v!=start)
    		{
    			s.push(v);
    			v = pre[G.getVertexPos(v)];
    		}
    		s.push(v);
    		while(!s.empty())
    		{
    			cout<<s.top()<<" ";
    			s.pop();
    		}
    	}	
    };
    //测试代码
    void test_Dijkstra()
    {
    	Graphmtx<char,int> G;//T为char,E为int
    	
    	G.inputGraph();
    	int *dist= new int[G.NumberOfVertices()];
    	char *pre = new char[G.NumberOfVertices()];
    	char start;
    	cout<<"输入源点:";
    	cin>>start;
    	Dijkstra(G,dist,pre,start);
    
    	for(int i = 0;i<G.NumberOfVertices();i++)
    	{
    		char end = G.getValue(i);
    		if(end!=start)
    		{
    			showPath(G,pre,end,start);
    			cout<<dist[i]<<endl;
    		}		
    	}
    }
    对于下图,进行测试:



  • 相关阅读:
    洛谷P2664 树上游戏(点分治)
    洛谷P3366 【模板】最小生成树(Boruvka算法)
    loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)
    noi.ac#309 Mas的童年(子集乱搞)
    loj#6041. 「雅礼集训 2017 Day7」事情的相似度(SAM set启发式合并 二维数点)
    Windows phone应用开发[22]-再谈下拉刷新
    Windows phone应用开发[21]-图片性能优化
    Windows phone应用开发[20]-禁止Pivot手势
    Windows phone应用开发[19]-RSA数据加密
    Windows phone应用开发[18]-下拉刷新
  • 原文地址:https://www.cnblogs.com/f8master/p/3826065.html
Copyright © 2011-2022 走看看