【Dijkstra算法】未优化版+优先队列优化版

https://blog.csdn.net/YF_Li123/article/details/74090301

 

Dijkstra算法伪代码:

//G为图;数组d为源点到达各点的最短路径长度,s为起点
Dijkstra(G, d[], s)
{
     初始化;
     for(循环n次)
     {
          u = 使d[u]最小的还未被访问的顶点的标号;
          记u已被访问;
          for(从u出发能到达的所有顶点v)
          {
               if(v未被访问 && 以u为中介点使s到顶点v的最短距离d[v]更优)
               {
                    优化d[v];
               }
          }
     }
}

邻接表:

const int INF = 1000000000;
 
struct Node
{
       int v;         //边的目标顶点
       int dis;       //dis为边权
       Node(int x, int y) :v(x), dis(y) {}
};
 
void Dijkstra(int n, int s, vector<vector<Node>> Adj, vector<bool> vis, vector<int>& d)
{
       /*
       param
       n:      顶点个数
       s:      起点
       Adj:    图的邻接表
       vis:    标记顶点是否被访问
       d:      存储起点s到其他顶点的最短距离
       */
       fill(d.begin(), d.end(), INF);
       d[s] = 0;                                             //起点s到达自身的的距离为0
       for (int i = 0; i < n; ++i)
       {
              int u = -1;                                    //找到d[u]中最小的u
              int MIN = INF;                                 //找到最小的d[u]
              for (int j = 0; j < n; ++j)   //寻找最小的d[u] {
                     if (vis[j] == false && d[j] < MIN){
                           u = j;
                           MIN = d[j];
                     }
              }
              //找不到小于INF的d[u],说明剩下的顶点和起点s不连通
              if (u == -1)return;
              vis[u] = true;                                //标记u被访问
              for (int j = 0; j < Adj[u].size(); ++j){
                     int v = Adj[u][j].v;                   //通过邻接表获取u能直接到达的v
                     if (vis[v] == false && d[v] > d[u] + Adj[u][j].dis)     
                           d[v] = d[u] + Adj[u][j].dis;       //优化d[u]
              }
       }
}

优先队列优化版:


/*
* 使用优先队列优化 Dijkstra 算法
* 复杂度 O(ElogE)
* 注意对 vector<Edge>E[MAXN] 进行初始化后加边
*/
const int INF=0x3f3f3f3f;

const int MAXN = 1000010;
struct qnode {
    int v;
    int c;
    qnode(int _v = 0, int _c = 0) : v(_v), c(_c){}
    bool operator<(const qnode &r) const{
        return c > r.c;
    }
};
struct Edge {
    int v, cost;
    Edge(int _v = 0, int _cost = 0) : v(_v), cost(_cost){}
};
vector<Edge> E[MAXN];
bool vis[MAXN];
int dist[MAXN];
// 点的编号从 1 开始
void Dijkstra(int n, int start)
{
    memset(vis, false, sizeof(vis));
    for (int i = 1; i <= n; i++)
        dist[i] = INF;
    priority_queue<qnode> que;
    while (!que.empty())
        que.pop();
    dist[start] = 0;
    que.push(qnode(start, 0));
    qnode tmp;
    while (!que.empty()) {
        tmp = que.top();
        que.pop();
        int u = tmp.v;
        if (vis[u])continue;
        vis[u] = true;
        for (int i = 0; i < E[u].size(); i++) {
            int v = E[tmp.v][i].v;
            int cost = E[u][i].cost;
            if (!vis[v] && dist[v] > dist[u] + cost) {
                dist[v] = dist[u] + cost;
                que.push(qnode(v, dist[v]));
            }
        }
    }
}
void addedge(int u, int v, int w){
    E[u].push_back(Edge(v, w));
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值