dijkstra 算法优先队列实现

本文详细介绍了如何使用优先队列优化Dijkstra算法的实现,通过实例代码展示了算法的具体步骤,包括查找距离起点最近的未访问顶点,并更新路径成本,实现了高效的最短路径搜索。

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

dijkstra 算法优先队列实现 

 

基于优先队列的算法实现其实很简单,

首先,我们要清楚dijkstra 算法的核心思想:

n次查找:

    1.每次查找距离起点s最近的 且未访问的顶点 u ,dist[u] 表示距离起点的最近的点的距离

    2.for(从 u 出发能到达的所有的顶点v):
        if(以 u 为中介点 能够使得 s 到顶点v的最短距离d[v]更优){
            优化d[v]
        }

而优先队列在这里做的一点就是,能够在查找最小未访问的点时,能够快速找到,使得 第一步能够以 logn的复杂度找到最小未访问点u

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

using namespace std;

struct node{
	int to,cost,rec;//目标,开销,反相边 
	node(){}
	node(int to,int cost,int rec):to(to),cost(cost),rec(rec){}
};
const int MAXN = 10000; 
vector<node> map_[MAXN];

const int INF = 0x3f3f3f3f;
void add_edge(int a,int b,int cost){
	map_[a].push_back(node(b,cost,map_[b].size()));
	map_[b].push_back(node(a,cost,map_[a].size()-1));
}

int dist[MAXN];
int N,M,start;
struct qnode{
	int len;
	int to;
	qnode(){}
	qnode(int to,int len):to(to),len(len){}
	
	bool operator <(const qnode & b) const{
		return len>b.len;
	}
};
void dijkstra(int start){
	
	fill(dist,dist+N,INF);
	dist[start] = 0;
	qnode temp(start,0);
	priority_queue<qnode> que;
	
	que.push(temp);
	while(!que.empty()){
		qnode temp = que.top(); que.pop();
        if(dist[temp.to] != temp.len) continue;
		for(int i=0;i<map_[temp.to].size();i++){
			node nnode = map_[temp.to][i];
			
			if(nnode.cost + dist[temp.to] < dist[nnode.to]){
				dist[nnode.to] = nnode.cost + dist[temp.to];
				que.push(qnode(nnode.to,dist[nnode.to]));
			}
		}
	}
}

int main(){


	scanf("%d%d%d",&N,&M,&start);
	for(int i=1;i<=M;i++){
		int a,b,cost;
		scanf("%d%d%d",&a,&b,&cost);
		add_edge(a,b,cost);
	}
	
	dijkstra(start);
	for(int i=0;i<N;i++){
		printf("%d ",dist[i]);
	}
	printf("\n");
	
	
	return 0;
}

 

input: 

6 8 0 // 6个顶点, 8条边, 0号为七点
0 1 1 // 边 0-> 1 权为 1 下同
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3

output: 

0 1 5 3 4 6
### Dijkstra算法的不同优先队列实现及其性能对比 #### 1. 堆(Heap) 堆是一种常用的优先队列数据结构,在Dijkstra算法中的应用非常广泛。当使用二叉最小堆作为优先队列时,插入操作的时间复杂度为O(log V),其中V表示图中节点的数量;提取最小值的操作同样具有这样的时间复杂度。因此,对于每条边执行松弛操作所需的总时间为E * O(log V)[^1]。 ```cpp struct cmp { bool operator() (pair<int, int> &a, pair<int, int> &b) { return a.second > b.second; } }; priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> pq; // C++ STL 中的优先队列 ``` #### 2. Fibonacci Heap Fibonacci heap 是一种更高效的优先队列变种,它能够提供更好的渐近运行时间。具体来说,减少键值的操作可以在均摊意义上达到常数级别O(1),而删除最小元素仍然保持在O(log n)内完成。这使得基于斐波那契堆版本的迪杰斯特拉算法整体效率更高,尤其是在处理稀疏图的情况下[E * O(1)] + [V * O(log V)]。 然而值得注意的是,尽管理论上看起来更快,但在实际编程实践中由于其较高的隐藏系数以及较为复杂的编码过程,fibonacci heap 并不一定总是优于简单的 binary 或者 d-ary heaps。 #### 3. 配置器数组(Bucket Queue / Array-based Priority Queue) 这种类型的优先队列适用于权重范围有限的情况。通过创建一个大小等于最大可能权值加一的数组来存储待访问结点列表,并利用索引来快速定位对应位置上的所有候选项。此方法允许我们在O(1)时间内找到并移除当前最短路径长度对应的顶点,但是增加了额外的空间开销并且只适合特定条件下的应用场景[V + E][^2]。 综上所述: | 数据结构 | 插入/更新 | 提取最小 | | -- | | Binary Min-Heap | O(log V) | O(log V) | | Fibonacci Heap | Amortized O(1), Extract-Min O(log V)| O(log V)| | Bucket Queue | O(1) | O(V) |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值