图中最短路径的两种经典算法(c++)

Floyd+Dijkstra

Shortpath.h

#pragma once
#include <iostream>
#include <stack>
#include "Graph_data.h"
//非邻接点之间的权重
const int MAX= 99;

void print();
void Floyd_init(const Graph &g);
void Floyd(const Graph &g,int s,int f);
void print_path(int s,int f);
void Dijkstra_init();
void Dijkstra(Graph &g, int s, int f);

Shortpath.cpp

#include "Shortpath.h"

using namespace std;

//最大顶点数
#define M 99

//Floyd算法
//距离矩阵
int f_dis[M][M];
//路径矩阵
int f_path[M][M];

//Dijkstra算法
//距离、路径数组
vector<int> d_path, d_dis;
//最终输出的路径(方便最后的打印)
stack<int> d_p;

//打印Floyd两个矩阵
void Floyd_print()
{
	cout << "距离矩阵" << endl;
	for (int i = 0; i < 9; ++i) {
		for (int j = 0; j < 9; ++j) {
			cout << f_dis[i][j] << " ";
		}
		cout << endl;
	}
	cout << "轨迹矩阵" << endl;
	for (int a = 0; a < 9; ++a) {
		for (int b = 0; b < 9; ++b) {
			cout << f_path[a][b]<< " ";
		}
		cout << endl;
	}
}
//Floyd中参数矩阵的初始化
void Floyd_init(const Graph &g)
{
	for (int j = 0; j < g.m_vernumber; ++j) {
		for (int k = 0; k < g.m_vernumber; ++k) {
			if (j != k) {
				f_dis[j][k] = MAX;
			}
			else {
				f_dis[j][k] = 0;
			}
			f_path[j][k] = k;
		}
	}
	//邻接节点之间填充权重
	int i = 0;
	Arc* temp = NULL;
	for (auto& it = g.m_vertable.begin(); it != g.m_vertable.end(); ++it) {
		temp = it->ver_next;
		while (temp != NULL) {
			f_dis[i][temp->arc_pos] = temp->arc_weight;
			temp = temp->arc_next;
		}
		++i;
	}
}

void Floyd(const Graph &g,int s,int f)
{
	Floyd_init(g);
	int len = 0;
	//floyd迭代
	for (int k = 0; k < g.m_vernumber; ++k) {
		for (int i = 0; i < g.m_vernumber; ++i) {
			for (int j = 0; j < g.m_vernumber; ++j) {
				len = f_dis[i][k] + f_dis[k][j];
				if (f_dis[i][j]>len) {
					f_dis[i][j] = len<MAX?len:MAX;
					f_path[i][j] = f_path[i][k];
				}
			}
		}
	}
	//Floyd_print();
	//输出最短距离以及路径
	//判断是否可达
	if (f_dis[s][f] >= MAX) {
		cout << s << "到" << f << "不可达" << endl;
		return;
	}
	cout << s << "到" << f << "的最短距离为:" << f_dis[s][f] << " 路线为:";
	//根据起始点输出路径
	//把路径储存在队列中
	deque<int> route;
	route.push_back(s);
	int temp=0;
	while (true) {
		temp = f_path[s][f];
		if (temp == f) {
			route.push_back(f);
			break;
		}
		s =temp;
		route.push_back(s);
	}
	//输出路径
	while (!route.empty()) {
		cout << route.front() << " ";
		route.pop_front();
	}
	cout << endl;
}

//Dijkstra中数组的初始化
void Dijkstra_init(const Graph &g)
{
	for (int i = 0; i < g.m_vernumber; ++i) {
		d_dis.push_back(MAX);
		d_path.push_back(0);
	}
	/*cout << "距离数组" << endl;
	for (int j = 0; j < g.m_vernumber; ++j) {
		cout << d_dis[j] << " ";
	}
	cout << endl;
	cout << "路径数组" << endl;
	for (int k = 0; k < g.m_vernumber; ++k) {
		cout << d_path[k] << " ";
	}
	cout << endl;*/
}
//根据路径数据输出最终的路径轨迹;
void get_path(int s,int f)
{
	int temp = d_path[f];
	d_p.push(temp);
	if (temp == s) {
		return;
	}
	else {
		get_path(s,temp);
	}
}

void Dijkstra(Graph &g, int s, int f)
{
	//dijkstra循环中的顶点栈
	//(起到循环的作用)
	stack<int> T;
	Dijkstra_init(g);
	d_dis[s] = 0;
	//将初始顶点设置为已经访问
	g.m_vertable[s].ver_viste = true;
	//初始顶点入栈
	T.push(s);
	while (!T.empty()) {
		int n = T.top();
		T.pop();
		//访问栈顶的顶点
		Ver temp_ver = g.m_vertable[n];
		int p,w,l;
		Arc* temp = temp_ver.ver_next;
		//访问该顶点的所有邻域顶点
		while (temp != NULL) {
			p = temp->arc_pos;
			w = temp->arc_weight;
			l = w + d_dis[n];
			//如果顶点未访问且距离小于原来的距离
			if (g.m_vertable[p].ver_viste != true && l < d_dis[p]) {
				//当前顶点的前驱顶点为其上一顶点之一
				d_path[p] = n;
				//更新起始点到当前顶点的最短距离
				d_dis[p] =l;
			}
			temp = temp->arc_next;
		}
		//遍历距离数组,获取未访问顶点中,距离起始点最小的顶点
		int min = MAX;
		int a = s;
		for (int i = 0; i < g.m_vernumber; ++i) {
			if (g.m_vertable[i].ver_viste != true && d_dis[i] < min) {
				min = d_dis[i];
				a = i;
			}
		}
		g.m_vertable[a].ver_viste = true;
		if (a != f) {
			T.push(a);
		}
	}
	//输出路径
	cout <<s<< "到" <<f<<"的最短距离:"<<d_dis[f]<<" ";
	cout << "最短路径为:";
	get_path(s,f);
	while (!d_p.empty()) {
		cout << d_p.top() << "->";
		d_p.pop();
	}
	cout << f << endl;
}

main.cpp

#include <iostream>
#include "Graph_data.h"
#include "Shortpath.h"
using namespace std;

int main()
{
	cout << "9点网络" << endl;
	Graph g1(9, 0,"9点网络.txt");
	g1.Creat_graph();
	cout << "Floyd" << endl;
	Floyd(g1,0,4);
	cout << "Dijkstra" << endl;
	Dijkstra(g1, 0, 4);

	cout << "5点负值网络" << endl;
	Graph g2(5, 0,"5点负值网络.txt");
	g2.Creat_graph();
	cout << "Floyd" << endl;
	Floyd(g2,1, 0);

	cout << "5点网络" << endl;
	Graph g3(5, 0, "5点网络.txt");
	g3.Creat_graph();
	cout << "Floyd" << endl;
	Floyd(g3,0,4);
	cout << "Dijkstra" << endl;
	Dijkstra(g3, 0, 4);

	cout << "5点等值网络" << endl;
	Graph g4(6, 0, "5点等值网络.txt");
	g4.Creat_graph();
	cout << "Floyd" << endl;
	Floyd(g4, 0, 5);
	cout << "Dijkstra" << endl;
	Dijkstra(g4, 0, 5);

	
	//Graph g2 = g1;
	//cout << "该图的DFS遍历:";
	//g1.Print_DFS();
	//cout << "该图的BFS遍历:";
	//g2.Print_BFS();
	system("pause");
	return 0;
} 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值