Dijkstra算法之优先队列优化版本 By ACReaper

来源:互联网 发布:mysql 数据导入mysql 编辑:程序博客网 时间:2024/05/19 18:48

Dijksta算法中,如果我们采用的是邻接矩阵来存的,第一点浪费的空间比较多,第二点我们知道算法的时间复杂度在O(n*n),这样的算法可以说并不是很好,所以我们考虑优化它,那么可以从哪些地方优化呢,首先我们可以优化存储结构,采用邻接表来存储,其次我们可以用优先队列来排序大小,其时间复杂度大大降低。代码如下。

需要注意的是pair是按照第一个元素的大小排序,如果相同才按照第二个,所以我们要把d[i]包装在第一个元素上。

还有这里必须掌握C++的优先队列容器,当然如果你要自己写,也可以,但是没有那个必要。这里的优先队列是这样的,有三个参数,第一个就是队列存的元素的数据类型,第二个我们用vector数组自动实现拓展,第三个是一个可选的排序方式,可以自己定义,也可以用默认的是 <,,代表着按照升序排列,优先队列中pop指向最后,top也是,push指向最前面。

#include <cstdio>#include <cstring>#include <limits>#include <queue>#define MAXN 1000using namespace std;int n,m;int next[MAXN + 1];//表示第i条边的nexr指针 int first[MAXN + 1];//表示第i个结点的next指针 int u[MAXN + 1],v[MAXN + 1];int w[MAXN + 1];int d[MAXN + 1];//用来表示到结点V1的最短长度int fa[MAXN + 1];//用来记录路径 typedef pair<int,int> pii;int main(){while(scanf("%d%d",&n,&m) != EOF){for(int i = 1; i <= n ; i++){first[i] = 0;}for(int e = 1; e <= m; e++){//建立图的邻接表 scanf("%d%d%d",&u[e],&v[e],&w[e]);next[e] = first[u[e]];first[u[e]] = e; }d[1] = 0,fa[1] = 1;//Init Dijkstra const int inf = std::numeric_limits<int>::max();for(int i = 2; i <= n; i++){d[i] = inf;fa[i] = 0;}priority_queue <pii,vector<pii>,greater<pii> >q;//优先队列bool done[MAXN + 1];memset(done,0,sizeof(done));//初始化doneq.push(make_pair(d[1],1));while(!q.empty()){pii u = q.top();q.pop();int x = u.second;if(done[x]) continue;done[x] = true;for(int e = first[x]; e != 0; e = next[e]){//由邻接表出发拓展于其相邻的结点 if(d[v[e]] > d[x] + w[e]){d[v[e]] = d[x] + w[e];fa[v[e]] = x;q.push(make_pair(d[v[e]],v[e]));} }}for(int i = 1; i <= n; i++){printf("%d ",d[i]);} }return 0;}

这段代码的效率大大的提高了。

2013 04 29

By ACReaper

原创粉丝点击