弗洛伊德算法--多源最短路径

17 篇文章 0 订阅
14 篇文章 0 订阅
//图的存储--邻接矩阵
#define  MAXSIZE 100
#define  INF 65535
typedef struct 
{
	int  edges[MAXSIZE][MAXSIZE];//存放边的关系的数组
	int  n,e;//n是顶点个数 e是边的个数
	char vex[MAXSIZE];//存放顶点信息
}MGrap;


 

//创建图。

//单元最短路径的实                    现
void createGrap(MGrap *g)
{

	cout <<"请输入顶点数和边的数"<<endl;
	cin>>g->n>>g->e;
	cout<<"请输入顶点信息"<<endl;
	for (int i =0;i<g->n;i++)
	{
		cin>>g->vex[i];
	}
	//初始化矩阵
	for (int i =0;i<g->n;i++)
	{
		for (int j =0;j<g->n;j++)
		{
			g->edges[i][j] = 65535;
		}
	}
	cout<<"请输入边的信息:起始边和终止边 以及值"<<endl;
	for (int i =0;i<g->e;i++)
	{
		int start, end,value;
		cin>>start>>end>>value;
		g->edges[start][end] = value;
	}
}
void Dijistra(MGrap g,int* dist,int* path,int v)
{
	int set[MAXSIZE];
	int min =0;
	int u =0;
	for (int i =0;i<g.n;i++)//选择一个起始点 并根据其他顶点到当前顶点的距离 初始化path数组
	{
		dist[i] = g.edges[v][i];
		set[i] = 0;
		if (g.edges[v][i]<INF)
		{
			path[i] = v;
		}
		else
		{
			path[i] = -1;
		}
	}

	set[v] =1;
	path[v]  = -1;//初始化起始顶点
	//关键操作开始
	
	for (int i =0;i<g.n-1;i++)
	{
		min =INF;
		/*
		这个循环每次从剩余顶点中选择一个顶点,从源点通往其他未并入S中的顶点路径是最短的
		*/
		for (int j =0;j<g.n;j++)
		{
			if (set[j]==0&&dist[j] <min)
			{
				u = j;
				min =dist[j];
			}
		}
	set[u] =1;//将选出的顶点并入最短路径中

	//这个循环以刚并入的顶点作为中间点,对所有通往集合T中的路径进行检测
	for (int k =0;k<g.n;k++)
	{
		//这个if判断新加入这个顶点是否会导致源点到T中的顶点的距离减少,如果减少,那么久更新最短距离和路径下标 
		//否则什么都不用做
		if (set[k]==0&& dist[u]+g.edges[u][k] <dist[k])
		{
			dist[k] =  dist[u]+g.edges[u][k];
			path[k] = u;
		}
	}
	}
	/*关键操作结束*/
	/*
	函数结束的时候,dist[]数组中存储的是源点到其余顶点的最短距离,path[]中存放的是v点到其余顶点的最短路径
	*/
}
//输出某个顶点的最短路径
//输出从u到v的最短路径上顶点序列
void printPath(int u,int v,int path[][MAXSIZE])
{
	if (path[u][v] == -1)
	{
		cout<<"当前顶点"<<endl;
	}
	else
	{

		int mid = path[u][v];
		printPath(u,v,path);
		printPath(mid,v,path);
	}

}

 

#include <iostream>
#include <stack>
using namespace std;
//
//  Dijistra.h
//  Dijistra
//
//  Created by 吴珝君 on 2018/12/25.
//  Copyright  ©   2018年 闲着也是贤者. All rights reserved.
//

//图的存储--邻接矩阵
#define  MAXSIZE 100
#define  INF 65535
typedef struct 
{
	int  edges[MAXSIZE][MAXSIZE];//存放边的关系的数组
	int  n,e;//n是顶点个数 e是边的个数
	char vex[MAXSIZE];//存放顶点信息
}MGrap;

//创建图。

//单元最短路径的实                    现
void createGrap(MGrap *g)
{

	cout <<"请输入顶点数和边的数"<<endl;
	cin>>g->n>>g->e;
	cout<<"请输入顶点信息"<<endl;
	for (int i =0;i<g->n;i++)
	{
		cin>>g->vex[i];
	}
	//初始化矩阵
	for (int i =0;i<g->n;i++)
	{
		for (int j =0;j<g->n;j++)
		{
			g->edges[i][j] = 65535;
		}
	}
	cout<<"请输入边的信息:起始边和终止边 以及值"<<endl;
	for (int i =0;i<g->e;i++)
	{
		int start, end,value;
		cin>>start>>end>>value;
		g->edges[start][end] = value;
	}
}

void Dijistra(MGrap g,int* dist,int* path,int v)
{
	int set[MAXSIZE];
	int min =0;
	int u =0;
	for (int i =0;i<g.n;i++)//选择一个起始点 并根据其他顶点到当前顶点的距离 初始化path数组
	{
		dist[i] = g.edges[v][i];
		set[i] = 0;
		if (g.edges[v][i]<INF)
		{
			path[i] = v;
		}
		else
		{
			path[i] = -1;
		}
	}

	set[v] =1;
	path[v]  = -1;//初始化起始顶点
	//关键操作开始
	
	for (int i =0;i<g.n-1;i++)
	{
		min =INF;
		/*
		这个循环每次从剩余顶点中选择一个顶点,从源点通往其他未并入S中的顶点路径是最短的
		*/
		for (int j =0;j<g.n;j++)
		{
			if (set[j]==0&&dist[j] <min)
			{
				u = j;
				min =dist[j];
			}
		}
	set[u] =1;//将选出的顶点并入最短路径中

	//这个循环以刚并入的顶点作为中间点,对所有通往集合T中的路径进行检测
	for (int k =0;k<g.n;k++)
	{
		//这个if判断新加入这个顶点是否会导致源点到T中的顶点的距离减少,如果减少,那么久更新最短距离和路径下标 
		//否则什么都不用做
		if (set[k]==0&& dist[u]+g.edges[u][k] <dist[k])
		{
			dist[k] =  dist[u]+g.edges[u][k];
			path[k] = u;
		}
	}
	}
	/*关键操作结束*/
	/*
	函数结束的时候,dist[]数组中存储的是源点到其余顶点的最短距离,path[]中存放的是v点到其余顶点的最短路径
	*/
}
void  printPath(int path[], int v)
{
	stack<int>  s;
	while(path[v]!= -1)
	{
		s.push(v);
		v= path[v];//孩子双亲表示法
	}
	s.push(v);
	while(!s.empty())
	{
		cout<<s.top()<<endl;
		s.pop();
	}
	
}
//多源最短路径--弗洛伊德算法
/*
算法过程:
1)设置两个矩阵A和Path,初始时将图的邻接矩阵赋值给A ,将矩阵中的Path中全部元素置为-1
2)以顶点k为中间顶点,k取0~(n-1)中的值.对图中所有顶点对{i,j}进行如下检测与修改
		如果A[i][j]>A[i][k]+A[k][j]的值,将Path[i][j] = k;否则什么都不做。
由上述弗洛伊德算法求解最短路径的一般过程可以写出以下弗洛伊德算法代码,其中定义两个二维
数组A[][]和path[][],用来保存上述矩阵A和Path
*/
void Floyd(MGrap g,int Path[][MAXSIZE])
{
	int A[MAXSIZE][MAXSIZE];
	//这个双循环对数组A[][]和Path[][]进行了初始化
	for (int i =0;i<g.n;i++)
	{
	for (int j =0;j<g.n;j++)
	{
		A[i][j] = g.edges[i][j];//将A[][]的值初始化为权值
		Path[i][j] = -1;
	}		
	}
	//下面这个三层循环是本算法的主要操作,完成了以k为中间点对所有的顶点对{i,j}进行检测和修改
	for (int i =0;i<g.n;i++)
	{
		for (int j =0;j<g.n;j++)
		{
			for (int k =0;k<g.n;k++)
			{
				if (A[i][j]>A[i][k]+A[k][j])
				{
					A[i][j] = A[i][k]+A[k][j];
					Path[i][j] = k;
				}
			}
		}
	}

}
//时间复杂度为O(n^3)
 int main()
{
	MGrap g ;
	int dist[MAXSIZE];
	int path[MAXSIZE];
	createGrap(&g);
	Dijistra(g,dist,path,0);
	printPath(path,6);
	system("pause");
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值