`

求最短路径(Floyd算法和Dijkstra算法)

 
阅读更多

一、Floyd算法

 

      假设 _vertex[i][j] 表示节点 i 到节点 j 的最短距离,那么在图中遍历其它的点 k 时,如果 _vertex[i][k] + _vertex[k][j] < _vertex[i][j] 时,就对 _vertex[i][j] 进行更新,即 _vertex[i][j] = _vertex[i][k] + _vertex[k][j],和动态规划的思想一样;

 

     假设 _vertexPath[i][j] 记录节点 i 到节点 j 的路径中最后一个节点,或者说最后一个节点的前一个节点(如果包括正在计算的节点j的话,那么在更新 _vertex 的时候,就可以记录下路径的最后一个节点。

 

代码如下:

 

#include <iostream>
#include <vector>
#include <cstring>
#include <stack>
using namespace std;

#define LL long long
#define ULL unsigned long long
#define LOOP( X, Y )  for( int X = 0; X < Y; X++ )

const LL MAX = 999999;

LL nodes = 0, egdes = 0;

void Floyd( vector< vector<int> >_vertex, vector< vector<int> >_vertexPath, LL nodes );
void PrintPath( int i, int j, vector< vector<int> >_vertex, vector< vector<int> >_vertexPath, LL nodes );
int main()
{
	cin>>nodes>>egdes;

	vector< vector<int> >_vertex( nodes, nodes );
	vector< vector<int> >_vertexPath( nodes, nodes );

	LOOP( i, nodes )
	{
		LOOP( j, nodes )
		{
			_vertex[i][j] = MAX;    //初始两个节点之间的距离为无穷大
		}
	}

	Floyd( _vertex, _vertexPath, nodes );

	LL start = 0, destinate = 0;

	cin>>start>>destinate;

	PrintPath(start, destinate, _vertex,_vertexPath,nodes);

	return 0;
}

void Floyd( vector< vector<int> >_vertex, vector< vector<int> >_vertexPath, LL nodes )
{
	LOOP( i, nodes )
	{
		LOOP( j, nodes )
		{
			_vertexPath[i][j] = i;  //初始节点i到节点j的路径最后一个节点为i
		}
	}

	LOOP( i, nodes )
	{
		LOOP( j, nodes )
		{
			LOOP( k, nodes )
			{
				if( _vertex[i][j] > _vertex[i][k] + _vertex[k][j] )
				{
					_vertex[i][j] = _vertex[i][k] + _vertex[k][j]; //更新最短路径的值
					_vertexPath[i][j] = k;   //记录节点i到节点j的最短路径中最后一个节点,或者说最后一个节点的前一个节点(如果包括正在计算的节点j的话)
				}
			}
		}
	}

	return;
}

//输出路径函数,
//参数说明: i : 表示起始点
//           j : 表示终点
void PrintPath( int i, int j, vector< vector<int> >_vertex, vector< vector<int> >_vertexPath, LL nodes )
{
	stack<int> Path;

	if( i != j )   //如果起点和终点不同才输出
	{
		cout<<_vertex[i][j]<<endl;

		LL k = j;

		do
		{
			k = _vertexPath[i][k];
			Path.push(k);      //因为每次存放的是最后一个节点,所以路径是倒着的,所以使用一个栈进行存储,反过来输出。
		}while( k != i );

		cout<<Path.top()+1;

		while( !Path.empty() )
		{
			cout<<"->"<<Path.top()+1;
		}
		cout<<endl;
	}

	return ;
}

 

 

二、Dijkstra算法

 

       设dist[i] 表示点 i 到原点source的最小距离,pass[i] 记录遍历过的点,1表示遍历过得,0表示未遍历,prev[i] 记录第 i 个节点的前一个节点,v[i][j] 表示节点 i 到节点 j 之间的距离,不可达的话,距离为MAX,步骤如下:

 

     1、令u动态地表示起始点,刚开始 u = source,对 dist[i] 进行初始化,u不可到达的点,dist[i] = MAX,可到达的点,则dist[i] = v[u][i], 同时记录节点 i 的前一个节点prev[i], 若节点可达,则prev[i] = u,否则prev[i] = -1,最后将 pass[u] = 1,表示原点已经遍历过了。

 

      2、对 u 周围的节点进行遍历,选择出距离节点 u 最短的节点 j ,这时 u = j,更新起始点,将prev[j] = source, 并将 pass[j] = 1;

 

      3、对所有的节点进行遍历,判断 dist[j] > dist[u] + v[u][j] 是否满足,即判断通过节点 u 到达节点 j 是否为最短的,如果满足条件,则对 dist[j] 进行更新,并将prev[j] = u。

 

代码如下:

#include <iostream>
#include <vector>
using namespace std;

#define LL long long 

const LL MAX = 999999999;


void Dijkstra( int nodes, int s, vector<LL> &dist, vector<int> &prev,  vector< vector<int> > v )
{
	vector<bool> passed(nodes);
	for( int i = 0; i < nodes; i++ )
	{
		dist[i] = v[s][i];
		passed[i] = false;   //初始每个节点都未遍历过
		if( dist[i] == MAX )
			prev[i] = -1;
		else
			prev[i] = s;
	}

	dist[s] = 0;      //初始s到s的距离为0
	passed[s] = true; //初始s已经遍历过

//依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
//一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
	for( int i = 1; i < nodes; i++ )
	{
		LL temp = MAX;
		int u = s;

//找出当前未使用的点j的dist[j]最小值
		for( int j = 0; j < nodes; j++ )
		{
			if( (!passed[j]) && dist[j] < temp )
			{
				u = j;
				temp = dist[j];
			}
		}
		passed[u] = true;  //把邻接点中距离最短的点加入到passed中

		更新dist
		for( int j = 0; j < nodes; j++ )
		{
			if( (!passed[j]) && (v[u][j] < MAX)  )
			{
				LL newdist = dist[u] + v[u][j];
				if( newdist < dist[j] )
				{
					dist[j] = newdist;
					prev[j] = u;
				}
			}
		}	

	}
}

int main()
{
	freopen("Dijkstra.in", "r", stdin);

	int nodes = 0;
	long long edges = 0;

	cin>>nodes;
	cin>>edges;

	vector< vector<int> >v(nodes,nodes);  //定义邻接矩阵
	vector<LL> dist(nodes);  //记录当前节点到源节点的最短路径长度
	vector<int> prev(nodes);  //记录当前节点的前一个节点

	for( LL i = 0; i < nodes; i++ )
	{
		for( LL j = 0; j < nodes; j++ )
		{
			v[i][j] = MAX;         //初始化将两点之间的距离为MAX
		}
	}

	int p = 0, q = 0, len = 0;
	for( int i = 0; i < edges; i++ )
	{
		cin>>p>>q>>len;
		v[p-1][q-1] = len;
		v[q][p] = len;  //加上这句,表示无向图
	}

	for( int i = 0; i < nodes; i++ )
	{
		dist[i] = MAX;   //初始化每个节点到源节点的路径长度为MAX
	}

	Dijkstra(nodes, 3, dist, prev, v);   //参数:节点个数, 源节点, dist数组,prev数组,v邻接矩阵

	cout << "源点到最后一个顶点的最短路径长度: " << dist[nodes-1] << endl;

	return 0;
}

 

 

分享到:
评论

相关推荐

    最短路径算法Dijkstra源代码

    最短路径算法Dijkstra是图论中的一个经典算法,由荷兰计算机科学家艾兹格·迪科斯彻在1956年提出。该算法主要用于寻找带权重的有向或无向图中,从一个特定顶点到其他所有顶点的最短路径。Dijkstra算法的核心思想是...

    用Dijkstra算法求图中单源最短路径

    "用Dijkstra算法求图中单源最短路径" Dijkstra算法是一种常用的图搜索算法,用于解决单源最短路径问题。单源最短路径问题是指从一个出发顶点到所有可达顶点的最短路径问题。Dijkstra算法的原理是通过将图中的每个...

    VS2010下基于QT4.8.2开发的计算城市间最短路径程序,运用floyd算法和dijkstra算法

    Dijkstra算法是解决单源最短路径问题的经典算法,由荷兰计算机科学家艾兹格·迪科斯彻提出。它从源节点开始,逐步扩展最短路径树,每次选取当前未标记且距离源节点最近的节点。在QT 4.8.2中实现Dijkstra算法,可以...

    最短路径floyd算法

    1. 负权边:与其他最短路径算法(如Dijkstra)不同,Floyd-Warshall可以处理包含负权边的图,只要图中不存在负权环。 2. 存在路径:Floyd-Warshall算法可以检测图中是否存在从顶点i到顶点j的路径。如果在算法结束后...

    最短路径Floyd算法具体演示.doc

    总之,Floyd算法和Dijkstra算法都是图论中的经典算法,分别解决了多点对多点和单源最短路径问题。在实际的计算机科学和工程中,这些算法有着广泛的应用,例如在网络路由、物流规划、社交网络分析等场景。通过编程...

    三种算法(Floyd、Dijkstra、SPFA)求单源点最短路径。

    本文将详细探讨三种经典的单源点最短路径算法:Floyd-Warshall算法、Dijkstra算法和SPFA(Shortest Path Faster Algorithm)。这些算法在处理不同的图结构和需求时各有优势。 首先,Floyd-Warshall算法是一种动态...

    floyd算法求最短路径

    Floyd算法,又称为Floyd-Warshall算法,是解决图论中最短路径问题的一种经典算法。该算法的核心思想是通过动态规划的方法,逐步更新图中所有节点之间的最短路径,最终得到任意两个节点间的最短路径。在实际应用中,...

    dijkstra与floyd方法求最短路径实验报告.docx

    实验选取两种经典算法——Dijkstra算法与Floyd算法,分别针对特定场景求解最短路径问题。通过本实验,学生能够: 1. 掌握最短路径的基础理论知识。 2. 熟悉Dijkstra算法与Floyd算法的工作原理及其适用场景。 3. 能够...

    C/C++手撕代码 算法实现 最短路径 Dijkstra算法与Floyd算法

    C/C++手撕代码 最短路径 Dijkstra算法与Floyd算法-C/C++手撕代码算法实现 最短路径算法实现 Dijkstra算法实现 Floyd算法实现

    最短路径算法c# 最短路径算法

    1. Dijkstra算法:Dijkstra算法是最常用的单源最短路径算法,由荷兰计算机科学家艾兹格·迪科斯彻提出。该算法通过维护一个优先队列(通常使用二叉堆实现)来保证每次找到当前未访问节点中最短路径。它适用于有向图...

    数据结构 c++ 最短路径Dijkstra和Floyd

    在这个专题中,我们将聚焦于两个经典图论中的最短路径算法:Dijkstra算法和Floyd-Warshall算法。 Dijkstra算法是由荷兰计算机科学家艾兹格·迪科斯彻提出的,主要用于解决单源最短路径问题。它是一种贪心算法,其...

    最短路径的C++算法

    在C++中,我们可以使用多种算法来解决这个问题,其中最著名的包括Dijkstra算法和Floyd-Warshall算法。Dijkstra算法适用于单源最短路径问题,而Floyd-Warshall则可以处理所有对之间最短路径的问题。 1. **Dijkstra...

    Floyd_Floydmatlab_最短路径算法_

    总的来说,Floyd算法是解决最短路径问题的强大工具,尤其在寻找所有顶点对之间最短路径的情况下。在MATLAB中,利用其强大的矩阵运算能力,可以便捷地实现和优化该算法,为图论问题的研究提供了便利。通过学习和实践...

    利用Floyd算法以及Dijkstra算法解决选址问题以及matlab代码文档

    - **步骤1**:同样使用Floyd算法或Dijkstra算法计算任意两点之间的最短路径。 - **步骤2**:对于每个小区i,计算其到其他所有小区的最短路径的加权和\(\sum P_j d_{ij}\)。 - **步骤3**:选择加权和最小的小区作为...

    最短路径经典算法

    最短路径问题在计算机科学和图论中是一个重要的研究领域,尤其在路由、网络优化、运输规划和游戏设计等多个领域有着广泛的应用。本压缩包文件的主题聚焦于“最短路径经典算法”,它提供了源码,使得开发者可以直接...

    Dijkstra算法找最短路径代码_dijkstra_Dijkstra算法找最短路径代码_dijkstra算法_

    Dijkstra算法,由荷兰计算机科学家艾兹格·迪科斯彻于1956年提出,是一种用于在图中寻找单源最短路径的算法。它适用于加权有向图或无向图,且所有边的权重都是非负的。这个算法的核心思想是通过逐步扩展最短路径树来...

    最短路径的Dijsktra算法及Floyd算法

    本文将详细探讨两种著名的解决最短路径问题的算法:Dijkstra算法和Floyd算法。 **Dijkstra算法** Dijkstra算法是由荷兰计算机科学家艾兹格·迪科斯彻在1956年提出的,它主要用于寻找带权重的无环图中从单一源点到...

    Floyd最短路径算法C++实现

    在提供的压缩包中,"Floyd求最短路径"可能是实现Floyd算法的C++源代码文件。通过阅读和理解这个文件,你可以学习如何在实际编程中运用Floyd算法,了解如何构建邻接矩阵,以及如何组织代码来执行动态规划步骤。 总的...

Global site tag (gtag.js) - Google Analytics