图最短路径算法

图最短路径算法

    • 迪杰斯特拉算法
    • 弗洛伊德算法
    • BFS

迪杰斯特拉算法

求原点0到其他点的最短路径
在这里插入图片描述

#include<iostream>
#include<vector>
#include<string.h>
#define N 10
#define INF 65535
using namespace std;

int graph[N][N];
int dist[N];
int parent[N];

// 迪杰斯特拉算法 
/*
找出源点到其他点的最短路径
核心思想:
	节点集合V, 已经被访问(找到最短路径)的集合S,和未被访问的集合W
	1.每次从W中找到一个距离S最近的点v1 (visited[v1] = false && dist[v1] < INF),  
	2.将v1 加入到集合S中,即visited[v1] = true
	3. 更新以v1为中转点, start -> ... -> v1 -> w w∈W的距离
		if (!visited[w] && (graph[v1][w] + dist[v1] < dist[w]) dist[w] = dist[v1] + graph[v1][w] 
	4. 循环n-1次,直到S中包含了所有节点,即W集合变为空集 
	
体现的是贪心思想: 每次从 W集合中找到一个离S最近的点w
	时间复杂度O(n^2)  
*/ 

int *dijkstra(int v0, int n) {
	//是否被访问数组
	bool visited[N] = {false}; 
	//距离数组
	//初始被访问节点 
	dist[v0] = 0;
	visited[v0] = true;
	int v1 = v0;
	parent[v0] = -1;
	//遍历其余n-1个点 
	for (int i = 1; i < n; i++) {
		int mind = INF;
		//找距离集合S(已经被访问) 最近的一个未被访问的点 
		for (int j = 0; j < n; j++) {
			// 核心过程--选点, 如果j在{V}-{S}中 
			if (!visited[j]) { 
				if (dist[j] < mind) {
					mind = dist[j];
					v1 = j;
				}
			}
		}
		//将v1点加入到被访问的集合S中 
		visited[v1] = true;
		// 更新以v1为中转点的节点的距离 
		for (int i = 0; i < n; i++) {
			if (!visited[i] && (dist[i] > dist[v1] + graph[v1][i])) {
				dist[i] = dist[v1] + graph[v1][i];
				parent[i] = v1;
			}
		} 
	}
	return dist; 
}

int main() {
	int ne = 10, nv = 6;
	int edges[][3] = {{0,1,2},{0,2,5},{1,2,1},{1,3,3},{2,3,3},{2,4,4},{2,5,1},{3,4,1},{3,5,4},{4,5,1}};
	
	//二维整型数组直接利用 memset() 函数初始化时,只能初始化为 0 或 -1 ,否则将会被设为随机值
	//手动初始化 
	for (int i = 0; i < nv; i++) {
		dist[i] = INF;
		for (int j = 0; j < nv; j++) {
			graph[i][j] = INF;
		}
	}
	//初始化边 
	int start = 0;
	for (int i = 0; i < ne; i++) {
		int v0 = edges[i][0];
		int v1 = edges[i][1];
		int w = edges[i][2];
		graph[v0][v1] = w;
		if (v0 == start) {
			dist[v1] = w;
			parent[v1] = v0;
		}
	}

	int *dist = dijkstra(start,nv);
	for (int i = 0; i < nv; i++) {
		cout << "start = "<<start << " end =" << i << " dist = "<< dist[i] << " parent = " << parent[i] << endl;
	} 
	return 0;
} 

/*
memset初始化二维矩阵
1取最后一个字节 2->16->10
00000001 -> 0x01010101 -> 16843009
0
00000000 -> 00000000
-1
11111111 ->  
https://blog.csdn.net/qq_53269459/article/details/119535151

dijkstra算法参考:https://baike.baidu.com/item/%E8%BF%AA%E5%85%8B%E6%96%AF%E7%89%B9%E6%8B%89%E7%AE%97%E6%B3%95/23665989 
*/

在这里插入图片描述

弗洛伊德算法

求所有点之间的最短路径

#include<iostream>
#include<vector>
#include<string.h>
#define N 10
#define INF 65535
using namespace std;

int graph[N][N];

/*
弗洛伊德算法
	求所有点之间的最短距离 
核心思想:
	经由中转点k所能得到的最短距离
	弗洛伊德是一种动态规划算法,u是起点,v是终点,k是中转点 
	for k
		for u
			for v
				dist[u][v] = min(dist[u][v],dist[u][k]+dist[k][v])
	时间复杂度O(n^3) 
问题:
	为什么是最外层为中转点k 
	因为floyd本质目的是对于每个点对i-j的距离可以被其它点优化,而且可以被多个点共同优化,
	如果循环k在内层,那么i,j每次只能得到一个点的优化。
	例如 
	1 -> 3 -> 4 ->2
	\ _ _ _ _ _ /
	点1-2的路径只能通过单一的点,k在最内部: 
	1与2之间的最短路径,要么通过3,要么通过4; 1->3->2, 和1->4->2; 没有考虑到同时使用3,4来优化,即1->3->4->2
参考:https://blog.csdn.net/RunningBeef/article/details/114683747 
*/ 

void floyed(int n) {
	//中间点 
	for (int k = 0; k < n; k++) {
		//起点 
		for (int v0 = 0; v0 < n; v0++) {
			//终点
			for (int v1 = 0; v1 < n; v1++) {
				if (graph[v0][k] + graph[k][v1] < graph[v0][v1]) {
					graph[v0][v1] = graph[v0][k] + graph[k][v1];
				} 
			} 
		} 
	}
}

int main() {
	int ne = 10, nv = 6;
	int edges[][3] = {{0,1,2},{0,2,5},{1,2,1},{1,3,3},{2,3,3},{2,4,4},{2,5,1},{3,4,1},{3,5,4},{4,5,1}};
	
	//二维整型数组直接利用 memset() 函数初始化时,只能初始化为 0 或 -1 ,否则将会被设为随机值
	//手动初始化 
	for (int i = 0; i < nv; i++) {
		for (int j = 0; j < nv; j++) {
			graph[i][j] = INF;
		}
		graph[i][i] = 0;
	}
	//初始化边 
	int start = 1;
	for (int i = 0; i < ne; i++) {
		int v0 = edges[i][0];
		int v1 = edges[i][1];
		int w = edges[i][2];
		graph[v0][v1] = w;
	}

	floyed(nv);
	for (int i = 0; i < nv; i++) {
		for (int j = 0; j < nv; j++) {
			cout << graph[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
} 

在这里插入图片描述

BFS

广度优先遍历求两个点之间的最短路径
当遍历到目标节点,停止遍历,BFS求的是start到end之间的直线距离

  1 -5
 /  \  \
0     3-4
 \ 2 / 

求0,4的最短路径

#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
typedef vector<vector<int>> VVI; 
typedef vector<int> VI;
#define rep(i,n) for(int i = 0, i < n; i++)

VI bfs(VVI &edges,int n, int org, int dst) {
	//建图 
	VVI g(n);
	for (VI e : edges) {
		int start = e[0], end = e[1];
		g[start].push_back(end);
		g[end].push_back(start); 
	}
	//初始化距离和父节点数组 
	VI dis(n,-1);
	VI fa(n,-1);
	//初始化队列 
	queue<int> q;
	q.push(org);
	dis[org] = 0; 
	fa[org] = -1;
	//bfs求解最短路径 
	while (!q.empty()) {
		int x = q.front();
		q.pop();
		for (int y : g[x]) {
			if (y == dst) {
				fa[y] = x;
				dis[dst] = dis[x] + 1;
				break;
			}
			if (dis[y] < 0) {
				fa[y] = x;
				dis[y] = dis[x] + 1;
				q.push(y);
			}
		}
		if (dis[dst] != -1) {
			break;
		}
	}
	cout << dis[dst] << endl;
	VI path;
	int x = dst;
	while(x != -1) {
		path.push_back(x);
		x = fa[x];
	}
	reverse(path.begin(),path.end());
	return path;
}

int main() {
	VVI edges = {{0,1},{0,2},{0,3},{1,3},{1,5},{2,3},{3,4},{5,4}};
	int n = 6;
	VI path = bfs(edges,n,0,4);
	for (int i = 0, n = path.size(); i < n; i++) {
		cout << path[i] << (i==n-1 ? "" : " -> ");
	}
	cout << endl;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/6742.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

达梦数据库DISQL常用命令

1.帮助 HELP 作用&#xff1a;可以帮助用户查看其他命令的具体用法。用户可以看到其他命令系统显示的内容。 语法如下&#xff1a; HELP <command> 示例如下&#xff1a; 2.输出文件 SPOOL 作用&#xff1a;将屏幕显示的内容输出到指定文件 语法如下&#xff1a; …

JVM 类的加载过程

文章目录1 类的生命周期2 类加载过程2.1 加载2.2 验证2.3 准备2.4 解析2.5 初始化3 类卸载1 类的生命周期 类从被加载到虚拟机内存中开始到卸载出内存为止&#xff0c;它的整个生命周期可以简单概括为 7 个阶段&#xff1a;&#xff1a;加载&#xff08;Loading&#xff09;、…

和开振学Spring boot 3.0之Spring MVC:③Spring MVC的配置

我们前面两篇做了基本的开发&#xff0c;相信大家对Spring MVC的流程有了基本的了解&#xff0c;这些我们来确认一下一些细节。 1、Spring MVC是如何初始化的 在Servlet 3.0规范中&#xff0c;web.xml再也不是一个必需的配置文件。为了适应这个规范&#xff0c;Spring MVC从3…

【数据结构】七种常见的排序

目录 1、排序的概念即运用 1.1、排序的概念 1.2、常见排序算法的分类 2、插入排序 2.1、排序原理 2.2、直接插入排序 2.3、希尔排序&#xff08;缩小增量排序&#xff09; 3、选择排序 3.1、直接选择排序 3.2、堆排序 4、选择排序 4.1、冒泡排序 4.2、快速排序 …

Android---Jetpack之Room

目录 应用实现 数据库升级 异常处理 Schema 文件 销毁和重建策略 预填充数据库 Android 采用 SQLite 作为数据库存储&#xff0c;开源社区常见的 ORM(Object Relational Mapping)库有ORMLite、GreenDAO等。Room 和其它库一样&#xff0c;也是在 SQLite 上提供了一层封装。…

一文懂交叉熵Cross-Entropy

本文翻译自https://naokishibuya.medium.com/demystifying-cross-entropy-e80e3ad54a8 交叉熵由交叉&#xff08;Cross&#xff09;和熵&#xff08;Entropy&#xff09;两部分组成&#xff0c;在机器学习中常常被定义为损失函数的目标。在二分类任务中&#xff0c;更有二分类交…

QT学习笔记(智能家居物联网项目实验2)

物联网项目综合测试 打开 4/01_smarthome/01_smarthome/01_smarthome.pro 项目&#xff0c;此项目为智能家居物联网 UI 界面控制端。 打开 4/01_smarthome/esp8266/esp8266.pro 项目&#xff0c;此项目设备端&#xff08;被控端&#xff09;。 打开上面两个项目如下。 项…

ToBeWritten之MOST协议、Flex Rat总线、车载以太网

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

C/C++每日一练(20230402)

目录 1. 找最大数和最小数 ※ 2. 数组排序 ※ 3. 按要求完成数据的输入输出 ※ &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 标注 ※ 为入门基础题&#xff0c;今天什么好日子CSDN…

一个有完整业务连的淘宝API接口

支持的业务类型 1、卖家平台&#xff08;包括淘宝网&#xff0c;天猫等&#xff09;&#xff1a;搜索、店铺信息维护、交易订单处理、发货管理、数据查询与统计分析。 2、买家平台&#xff08;包括淘宝&#xff0c;天猫等&#xff09;&#xff1a;搜索&#xff0c;发布信息&a…

银行数字化转型导师坚鹏:金融科技如何赋能银行数字化转型

金融科技如何赋能银行数字化转型课程背景&#xff1a; 数字化背景下&#xff0c;很多银行存在以下问题&#xff1a; 不清楚5G如何赋能银行数字化转型&#xff1f; 不清楚金融科技如何赋能银行数字化转型&#xff1f; 不了解银行数字化转型标杆成功案例&#xff1f; 课程特色…

旅游市场迎来“开门红”,VR云游带来全新体验

旅游业是一个充满活力和吸引力的行业&#xff0c;可以促进当地经济发展和提高生活水平。在清明时节&#xff0c;春暖花开&#xff0c;各地旅游市场正在回暖&#xff0c;而各大景区也纷纷推出了优惠措施&#xff0c;吸引大批的游客前来游玩&#xff0c;旅游市场迎来了“开门红”…

ServletAPI的使用

目录 一、HttpServlet 1.1 HttpServlet的核心方法 1.2 Servlet的生命周期 1.3 代码示例&#xff1a;通过postman来发送请求 1.4 代码示例&#xff1a;通过ajax来发送请求 二、HttpServletRequest 2.1 代码示例&#xff1a;打印请求信息&#xff1a; 2.2 代码示例&#…

强化学习——初探强化学习

本文引自&#xff1a;《 动手学强化学习 》 第 1 章 初探强化学习 1.1 简介 亲爱的读者&#xff0c;欢迎来到强化学习的世界。初探强化学习&#xff0c;你是否充满了好奇和期待呢&#xff1f;我们想说&#xff0c;首先感谢你的选择&#xff0c;学习本书不仅能够帮助你理解强…

COI实验室技能:python控制相机的方法——采集、处理、显示、实时

COI实验室技能&#xff1a;python控制相机的方法——采集、处理、显示、实时本文介绍如何利用python控制办公摄像头、工业相机和科研相机。将数据采集和处理统一到python代码中。   主要围绕解决采用什么库、掌握这个库的控制相机方法(参数配置、读取数据等等)、结合自己的算…

Go 反射

目录 什么是反射 反射的弊端 reflect 包 Go 提供的反射方法 type Type 类型 type Kind 类型 TypeOf ValueOf 什么是反射 ​反射&#xff08;reflection&#xff09;是在 Java 出现后迅速流行起来的一种概念&#xff0c;通过反射可以获取丰富的类型信息&#xff0c;并可…

实战!项目管理实施过程的五大难点和痛点

作为一个在项目摸爬滚打十余年的管理人员&#xff0c;对项目管理的难点和痛点深有体会&#xff0c;这就结合我自身体验来说一说。 我认为&#xff0c;项目管理实施中的难点和痛点其实可以归结为两类&#xff1a;一类是对于项目任务本身&#xff0c;另一类则涉及到团队内部的管…

2023年,转行学Java还是web前端?

2023年要想顺利入行IT建议选择Java。 理由很简单&#xff0c;前端开发岗位需求大量减少&#xff0c;大厂裁员导致大量有经验的前端开发人员或者初级后端开发人员流入就业市场&#xff1b;作为新人缺乏技能优势和项目优势&#xff0c;而用人单位也更愿意招聘熟手&#xff0c;或…
最新文章