C++学习第六篇——最短路

本文深入探讨了图论中的核心算法——最短路径算法,包括Dijkstra算法、Floyd算法及Bellman-Ford算法。重点讲解了Dijkstra算法的实现细节与应用场景,以及Floyd算法解决所有对之间最短路径问题的优势与不足。适合初学者和进阶学习者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最短路是图论最重要的算法之一,也是算法难点。经过这篇的学习,你会发现你离成功就差一个最短路的距离。=.=
最短路是指,某个点到某个点之间的距离最短。

算法1:Dijkstra算法

迪杰斯特拉算法是很典型的单源最短路算法,而且时间复杂度较其他算法更低,唯一的缺点是无法判断含负权边的图的最短路。而且其仅能作为单源最短路,也就是一个起点、一个终点求最短。在开始前推荐大家先去看我的另一篇博客最小生成树其中的prim算法和这个很类似。
同样由于技术有限,仅靠文字和代码讲解。-_-

int pic[1005][1005];//存图 

在输入之前,初始化图,将各点之间的距离设置为最大值,表示无法到达。
这里的图是单向的。

void init()
{
	for(int i=0;i<1005;i++)
	{
		for(int j=0;j<1005;j++)
		{
			pic[i][j]=(1<<21);//最大值可以自己设定,只要能表示不可达即可
		}
	}
}

dijkstra模板函数如下
特别强调c++和java不同,新开的数组会沿用之前相同名字的内存地址,所以赋值false很关键。之前我的模板错误在此
另外注意起点下标0-n-1或者1-n需要更改

void dijkstra()
{
	int weight[1005];//起始到其他端点的值 
	bool visit[1005];
	for(int i=0;i<n;i++)
	{
		weight[i]=pic[0][i];//将图中0到各个端点的值赋给weight数组 
		visit[i]=false;
	}
	weight[0]=0;
	visit[0]=true;
	//此时起点为0
	while(true)//0点作为起始点,从下一个点开始 
	{
		int j=0,k=-1,min=(1<<21);
//weight内的值为0时表示,已经访问过 
//遍历weight数组,寻找一个最小值,并且该点没有被访问过 
		while(j<n)
		{
			if(min>weight[j]&&!visit[j])
			{
				min=weight[j];
				k=j;//用k存下这个节点 
			}
			j++;
		} 
//已知的min是我当前起始节点到k节点的距离,已知连接边中最短的 
		if(k==-1) break;
		visit[k]=true;//访问过该节点 
//自此形成从起始到K的边,将其连接
 		for(int m=0;m<n;m++)
		{
		 	if(weight[m]>pic[k][m]+weight[k]&&!visit[m])
		 	{
		 		weight[m]=pic[k][m]+weight[k]; //将单点间距离与新更新值距离比较求最小
			}
		} 
	} 
}

和prim唯一一点不同的是,其他点存的距离为一段距离,未连接之前是最大值,连接过后就是某一段加某一段,weight数组里面存的是起始点到各点之间的距离。

  • 技巧:当你需要多源最短路而苦于Floyd的算法复杂度时,你不妨换种思路,把终点当做起点,而你需要求的其他顶点到终点的距离自然就有了。
算法2:Floyd算法

唯一的缺点就是时间复杂度过高(On^3),在算法实现时需要注意arr[i][k]+arr[k][j]的溢出问题所以可能需要long long数组。

void floyd()//算法模板 
{
	for(int k=0;k<=n;k++)
		for(int i=0;i<=n;i++)
			for(int j=0;j<=n;j++)
				if(arr[i][j]>arr[i][k]+arr[k][j])
					arr[i][j]=arr[i][k]+arr[k][j];
}

n表示点的个数,arr里面存取的是点到点的路径值,经过算法计算后,点到点的距离即为最小,可以求各个点之间的。

算法3:bellman-ford算法

之前遗漏,有待补充

### 实现 C++ 中类似于 Java 的 ArrayList 功能 在 C++ 中,`std::vector` 是接近于 Java `ArrayList` 的数据结构。它是一个动态数组,能够自动调整大小以容纳更多的元素,并提供了丰富的操作接口来管理容器内的元素。 以下是关于如何使用 `std::vector` 来模拟 Java 中的 `ArrayList` 功能: #### 使用 `std::vector` 进行动态数组的操作 `std::vector` 提供了许多与 Java `ArrayList` 类似的功能,例如动态扩展、随机访问以及迭代器支持等。下面是一些常见的用法示例[^4]: ```cpp #include <iostream> #include <vector> int main() { // 创建一个 vector 容器 std::vector<int> vec; // 添加元素到 vector (相当于 Java 的 add 方法) vec.push_back(10); vec.push_back(20); // 访问元素 (通过索引访问) int firstElement = vec[0]; // 获取第一个元素 int secondElement = vec.at(1); // 另一种获取第二个元素的方式 // 遍历 vector (相当于 Java 的 forEach 或增强型 for 循环) for (const auto &item : vec) { std::cout << item << " "; } // 删除后一个元素 (相当于 Java 的 removeLast()) vec.pop_back(); // 清空整个 vector (相当于 Java 的 clear()) vec.clear(); } ``` 上述代码展示了如何创建、添加、删除和遍历 `std::vector` 中的内容。需要注意的是,虽然两者都提供类似的动态特性,但在底层实现上存在差异:`std::vector` 基于连续内存分配,而 Java 的 `ArrayList` 则依赖对象引用机制[^5]。 #### 关于短路逻辑的支持 如果需要实现在某些条件下提前终止处理流程(即所谓的“短路”),可以通过标准库算法配合 lambda 表达式完成此目标。例如,在寻找满足特定条件的第一个元素时可采用如下方法[^6]: ```cpp #include <algorithm> #include <iostream> #include <vector> bool isEven(int num){ return num % 2 == 0; } int main(){ std::vector<int> numbers {1,3,5,7,8}; // 查找第一个偶数并停止进一步查找 auto it = std::find_if(numbers.begin(),numbers.end(),isEven); if(it != numbers.end()){ std::cout<<"First even number:"<<*it<<'\n'; }else{ std::cout<<"No even number found.\n"; } } ``` 这里利用了 STL 算法函数 `std::find_if()` 结合自定义谓词实现了类似 Java Stream API 中 short-circuiting 的行为模式[^7]。 #### 设置无效服务器名称匹配器的例子转换成C++ 对于设置 SNI 匹配器的需求,则需借助 Boost.Asio 或 OpenSSL 库自行构建相应功能模块,因为原生 C++ 并未直接内置此类网络层高级抽象概念[^8]。 ```cpp // 示例仅作示意用途;实际应用可能更复杂 struct SNIMatcher {}; class SSLParameters {}; void setInvalidServerNamePatternForHostName(SSLParameters& params){ SNIMatcher matcher = createSNIMatcher(""); std::vector<SNIMatcher> matchers{matcher}; params.setSNIMatchers(matchers); } ``` 尽管语法有所变化,但核心思路保持一致——通过组合多个组件形成终配置结果。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值