[手撕数据结构] 最短路径Dijkstra算法与Floyd算法

两种比较常见的最短路径问题 一个是求某个原点到其余各个顶点的最短路径,另一种是求每一对顶点之间的最短路径,相对应的就是Dijkstra算法与Floyd算法 本文测试样例如下图

Dijkstra算法

迪杰斯特拉算法是一个按路径长度递增的次序产生最短路径的算法

代码如下

#include <iostream>
#include<algorithm>
using namespace std;
#define MVNum 100      //最大顶点数
#define MAXInt 10086      //极大值
typedef struct Mgraph
{
	char vexs[MVNum];                     //顶点表
	int arcs[MVNum][MVNum];               //邻接矩阵
	int vexnum;               //图的当前点数
	int arcnum;               //图的当前边数
}AMGraph;//Adjacency Matrix Graph
int LocateVex(AMGraph* G, char v)//找到结点V在图G中的位置 即下标
{
	for (int i = 0; i < G->vexnum; i++)
	{
		if (G->vexs[i] == v)
		{
			return i;
		}
	}
	cout << "没找到" << endl;
	return 0;
}
/*因为是有向网 所以赋权值的时候不应G->arcs[i][j] = G->arcs[j][i] = w; 应该G->arcs[i][j] = w;即可*/
void CreatAMG(AMGraph* G)//邻接矩阵表示法创建有向网
{
	cout << "请输入图的总顶点数与总边数: ";
	cin >> G->vexnum >> G->arcnum;//输入总顶点数 总边数
	cout << "输入点的信息: ";
	for (int i = 0; i < G->vexnum; i++)
	{
		cin >> G->vexs[i];
	}
	for (int i = 0; i < G->vexnum; i++)//初始化
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j] = MAXInt;
		}
	}
	char v1, v2;//相连结点
	int w;//权值
	cout << "输入相连结点及边的权值" << endl;
	for (int k = 0; k < G->arcnum; k++)//构造邻接矩阵
	{
		cin >> v1 >> v2 >> w;//表示v1有通往v2的路 即v1->v2
		int i = LocateVex(G, v1);
		int j = LocateVex(G, v2);
		G->arcs[i][j]= w;
	}
	cout << "邻接矩阵如下" << endl;
	for (int i = 0; i < G->vexnum; i++)
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			cout << G->arcs[i][j] << " ";
		}
		cout << "\n";
	}
	return;
}

bool S[MVNum];//记录从原点v0到终点vi是否已被确定最短路径 true表示确定
int Path[MVNum];//记录从原点到终点vi的当前最短路径上vi的直接前驱顶点序号 否则为-1
int D[MVNum];//记录从原点到终点vi的当前最短路径 有弧则为权值 否则为∞

void ShortestPath_DIJ(AMGraph* G, int v0)
{
	int n = G->vexnum;
	int v = 0;
	for (int i = 0; i < n; i++)//初始化
	{
		S[i] = false;                      //S初始化为空集
		D[i] = G->arcs[v0][i];             //将V0到各个终点的最短路径长度初始化为弧上的权值
		if (D[i] < MAXInt)                 //如果v0到v之间有弧则将v的前驱置为v0
			Path[i] = v0;                               //无弧则置为-1
		else
			Path[i] = -1;
	}
	S[v0] = true;                            //将v0并入S集
	D[v0] = 0;                               //源点到源点的距离为0
	/*------------主循环 每次求得v0到某个顶点v的最短路径 并将V加入S集*/
	for (int i = 1; i < n; i++)
	{
		int min = MAXInt;
		for (int w = 0; w < n; w++)
		{
			if (!S[w] && D[w] < min)
			{
				v = w;
				min = D[w];
			}                      //选择一条当前最短路径,终点为v
			S[v] = true;           //将V加入S
			for (int w = 0; w < n; w++)//更新最短路径长度
			{
				if (!S[w] && D[v] + G->arcs[v][w] < D[w])
				{
					D[w] = D[v] + G->arcs[v][w];//更新D[w]
					Path[w] = v;//更新前驱
				}
			}
		}
	}
}
int main()
{
	AMGraph* G = (AMGraph*)malloc(sizeof(AMGraph));
	if (G == NULL)
	{
		cout << "空间不足 创建失败" << endl;
		return 0;
	}
	CreatAMG(G);
	ShortestPath_DIJ(G, 0);
	for (int i = 0; i < G->vexnum; i++)
	{
		cout << G->vexs[0] << "--" << G->vexs[i] << "的最短路径为:" << D[i] << endl;
	}
	return 0;
}

测试结果如下

 此程序设置的极大值MAX为10086 

Floyd算法

代码如下  可以大致将Floyd算法看成是Dijkstra算法Plus

#include <iostream>
#include<algorithm>
using namespace std;
#define MVNum 100      //最大顶点数
#define MAXInt 10086      //极大值
typedef struct Mgraph
{
	char vexs[MVNum];                     //顶点表
	int arcs[MVNum][MVNum];               //邻接矩阵
	int vexnum;               //图的当前点数
	int arcnum;               //图的当前边数
}AMGraph;//Adjacency Matrix Graph
int LocateVex(AMGraph* G, char v)//找到结点V在图G中的位置 即下标
{
	for (int i = 0; i < G->vexnum; i++)
	{
		if (G->vexs[i] == v)
		{
			return i;
		}
	}
	cout << "没找到" << endl;
	return 0;
}
/*因为是有向网 所以赋权值的时候不应G->arcs[i][j] = G->arcs[j][i] = w; 应该G->arcs[i][j] = w;即可*/
void CreatAMG(AMGraph* G)//邻接矩阵表示法创建有向网
{
	cout << "请输入图的总顶点数与总边数: ";
	cin >> G->vexnum >> G->arcnum;//输入总顶点数 总边数
	cout << "输入点的信息: ";
	for (int i = 0; i < G->vexnum; i++)
	{
		cin >> G->vexs[i];
	}
	for (int i = 0; i < G->vexnum; i++)//初始化
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j] = MAXInt;
		}
	}
	char v1, v2;//相连结点
	int w;//权值
	cout << "输入相连结点及边的权值" << endl;
	for (int k = 0; k < G->arcnum; k++)//构造邻接矩阵
	{
		cin >> v1 >> v2 >> w;//表示v1有通往v2的路 即v1->v2
		int i = LocateVex(G, v1);
		int j = LocateVex(G, v2);
		G->arcs[i][j] = w;
	}
	cout << "邻接矩阵如下" << endl;
	for (int i = 0; i < G->vexnum; i++)
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			cout << G->arcs[i][j] << " ";
		}
		cout << "\n";
	}
	return;
}
int Path[MVNum][MVNum];
int D[MVNum][MVNum];

void ShortestPath_Floyd(AMGraph* G)
{
	for (int i = 0; i < G->vexnum; i++)
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			D[i][j] = G->arcs[i][j];
			if (D[i][j] < MAXInt && i != j)//i j 有弧 则将j的前驱置为i
				Path[i][j] = i;
			else
				Path[i][j] = -1;//否则置位-1
			
		}
	}
	for (int k = 0; k < G->vexnum; k++)
	{
		for (int i = 0; i < G->vexnum; i++)
		{
			for (int j = 0; j < G->vexnum; j++)
			{
				if (D[i][k] + D[k][j] < D[i][j])// i 经过 k 到达 j 的一条路径更短
				{
					D[i][j] = D[i][k] + D[k][j];//更新D[i][j]
					Path[i][j] = k;//将j的前驱置为k
				}
			}
		}
	}
}
int main()
{
	AMGraph* G = (AMGraph*)malloc(sizeof(AMGraph));
	if (G == NULL)
	{
		cout << "空间不足 创建失败" << endl;
		return 0;
	}
	CreatAMG(G);
	ShortestPath_Floyd(G);
	for (int i = 0; i < G->vexnum; i++)
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			cout << G->vexs[i] << "-->" << G->vexs[j] << "的最短路径为" << D[i][j]<<endl;
		}
	}
	return 0;
}

测试结果如下

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值