迪杰斯特拉算法实现最短路径

172f2488741b4a3e9bfe91426a6798d3.png1.用邻接表实现

1.先写出一个邻接表

 

#include <iostream>
#include <vector>
#include<queue>

using namespace std;

// 定义边结构体
struct Edge {
	int to; // 边指向的顶点
	int weight; // 边的权重,如果图是无权重的,可以省略这个成员
};

// 邻接表类
class AdjacencyList {
private:
	vector<vector<Edge>> adjacencyList; // 邻接表
	vector<int>distances;               //存储每个节点到原点的距离
public:
	// 获取邻接表
	vector<vector<Edge>>& getAdjacencyList() {
		return adjacencyList;
	}

	// 构造函数
	AdjacencyList(int numVertices) : adjacencyList(numVertices), distances(numVertices, INT_MAX) {}

	// 添加边(无向图)
	void addEdge(int from, int to, int weight = 1) {
		//{ to, weight }在这里创建了一个std::pair对象,用于存储边的信息,并将其添加到邻接表中。
		//{ to, weight }是一个std::pair,它包含两个值:to(表示边的终点顶点的编号)和weight(表示边的权重)。
		adjacencyList[from].push_back({ to, weight });
		adjacencyList[to].push_back({ from, weight }); // 无向图需要添加反向边
	}

	//dijiskstra获取最短路径
	vector<int>getShortestPath(int source) {
		//优先队列
		priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
		//0-0的最短路径为0
		pq.push({ 0,source });
		//存储0到原点的距离为0
		distances[source] = 0;

		while (!pq.empty()) {
			//获取队列顶的元素0=current,将0到0的最短路径pop出队列-因为此时获取的队列顶元素有两个,一个是最短路径,一个是元素编号。所以使用auto自动识别元素类型
			auto current = pq.top();
			pq.pop();
			int currentDistance = current.first;//提取当前顶点到源顶点的最短路径长度。
			int currentVertex = current.second; //提取当前顶点的编号。

			//获取当前顶点所链接的所有点
			for (const Edge& edge : adjacencyList[currentVertex]) {
				//定义neighbor为当前顶点所连接的点
				int neighbor = edge.to;
				//定义newDistance为原点到当前点的最新的最短路径=原点到上一个点的最短路径+上一个点到当前点的权值
				int newDistance = currentDistance + edge.weight;
				//如果当前的最新最短路径小于链接当前节点的另一个节点的最短路径,则将原点到当前节点的值重新更新为newDistance
				if (newDistance < distances[neighbor]) {
					distances[neighbor] = newDistance;
					//更新完后将最短路径压入pq队列
					pq.push({ newDistance,neighbor });
				}
			}
		}
		return distances;
	}

	// 打印邻接表
	void print() {
		for (int i = 0; i < adjacencyList.size(); ++i) {
			cout << "Vertex " << i << ": ";
			for (const Edge& edge : adjacencyList[i]) {
				cout << "(" << edge.to << ", " << edge.weight << ") ";
			}
			cout << endl;
		}
	}

};

int main() {
	// 创建一个有6个顶点的邻接表
	AdjacencyList graph(6);

	// 添加边
	graph.addEdge(0, 1, 1);
	graph.addEdge(0, 2, 12);
	graph.addEdge(1, 2, 9);
	graph.addEdge(1, 3, 3);
	graph.addEdge(2, 3, 4);
	graph.addEdge(2, 4, 5);
	graph.addEdge(3, 4, 13);
	graph.addEdge(3, 5, 15);
	graph.addEdge(4, 5, 4);

	// 打印邻接表
   /* graph.print();*/

	vector<int>getnum = graph.getShortestPath(0);
	for (int num : getnum) {
		cout << num << endl;
	}
	return 0;
}

迪杰斯特拉算法实现最短路径函数

//欧氏距离
int OS(int x1, int y1,int x2,int y2) {
	return sqrt((x1-x2)* (x1 - x2) +(y1-y2)* (y1 - y2));
}

//dijiskstra获取最短路径
vector<int>getShortestPath(int source) {
	//优先队列
	priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
	//0-0的最短路径为0
	pq.push({ 0,source });
	//存储0到原点的距离为0
	distances[source] = 0;

	while (!pq.empty()) {
		//获取队列顶的元素0=current,将0到0的最短路径pop出队列-因为此时获取的队列顶元素有两个,一个是最短路径,一个是元素编号。所以使用auto自动识别元素类型
		auto current = pq.top();
		pq.pop();
		int currentDistance = current.first;//提取当前顶点到源顶点的最短路径长度。
		int currentVertex = current.second; //提取当前顶点的编号。

		//获取当前顶点所链接的所有点
		for (const Edge& edge : adjacencyList[currentVertex]) {
			//定义neighbor为当前顶点所连接的点
			int neighbor = edge.to;
			//定义newDistance为原点到当前点的最新的最短路径=原点到上一个点的最短路径+上一个点到当前点的权值
			int newDistance = currentDistance + edge.weight;
			//如果当前的最新最短路径小于链接当前节点的另一个节点的最短路径,则将原点到当前节点的值重新更新为newDistance
			if (newDistance < distances[neighbor]) {
				distances[neighbor] = newDistance;
				//更新完后将最短路径压入pq队列,使后序查看与neighbor所连接的点
				pq.push({ newDistance,neighbor });
			}
		}
	}
	return distances;
}

1.用欧氏距离计算函数算出两个坐标点之间的距离

7c57b76163cf4b0196509eed48432ca7.png

 

2.用优先队列实现最短路径问题

 

1.先创建出一个优先队列pq,用pair类接受两个数据一个为当前点到原点的最短路径,一个为当前节点的定点编号,将输入队列的数据按最短路径长度从小到大排列,将原点0输入进队列,并用distances数组记录0-0的最短路径为0;

//优先队列
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
//0-0的最短路径为0
pq.push({ 0,source });
//存储0到原点的距离为0
distances[source] = 0;

2.当队列不为空时,一直寻找原点到当前顶点的最短路径,首先定义一个连变量current获取到此时队列的队首元素,然后将当前元素pop出队列,定义curentDistance获取当前pair类的第一个元素(当前顶点到原点的最短路径),定义currentVertex获取当前pair类的第二个元素(为当前顶点的编号)

int currentDistance = current.first;//提取当前顶点到源顶点的最短路径长度。
int currentVertex = current.second; //提取当前顶点的编号。

3.用for循环获取当前顶点所连接的所有点,定义neighbor为当前点所连接的顶点编号,定义newDistance为当前点到原点的最短路径=(上一个顶点到远点的最短路径+当前顶点到上一个顶点的边权)     如果当前顶点的最短路径小于当前节点所连接的另一个节点的最短路径,就更新当前节点的最短路径为新的最短路径,最后,将当前节的最短路径和当前顶点的编号输入优先队列pq,以进行下次的最短路径寻找;

	//获取当前顶点所链接的所有点
	for (const Edge& edge : adjacencyList[currentVertex]) {
		//定义neighbor为当前顶点所连接的点
		int neighbor = edge.to;
		//定义newDistance为原点到当前点的最新的最短路径=原点到上一个点的最短路径+上一个点到当前点的权值
		int newDistance = currentDistance + edge.weight;
		//如果当前的最新最短路径小于链接当前节点的另一个节点的最短路径,则将原点到当前节点的值重新更新为newDistance
		if (newDistance < distances[neighbor]) {
			distances[neighbor] = newDistance;
			//更新完后将最短路径压入pq队列,使后序查看与neighbor所连接的点
			pq.push({ newDistance,neighbor });
		}
	}
}
return distances;

 

 

  • 27
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值