最短路算法——Dijkstra以及它的优化

示例图

代码

#include <iostream>
#include <math.h>
#include <algorithm>
#include <stdlib.h>
#include <stdio.h>
#include <iomanip>
#include <string.h>
#include <vector>
#include <set>
#include <map>
#include <iomanip>
#include <string>
#include <sstream>
#include <queue>

using namespace std;
const int INF = 99999999;

int index=0;//用于制定插入元素在数组中的位置
struct edge
{
    int v;//终点
    int next=0;//下一条边所存储的位置
    int len=INF;//边的长度
};
//用于存放边,按照链式向前星的
edge edges[100];
//用于记录均以某一顶点为起点的边所存的链表的起始点的位置
int head[10]= {0};

//添加边的操作,这里是有向图
void addedge(int from,int to,int len)
{
    index++;
    edges[index].len = len;
    edges[index].v = to;
    edges[index].next = head[from];
    head[from]=index;
}

int lens[10];
int visited[10]= {0};
//复杂度为O(n^2)
void dijkstra(int n,int u)
{
    for(int e=head[u]; e!=0; e=edges[e].next)
    {
        lens[edges[e].v]=edges[e].len;
    }
    lens[u]=0;
    visited[u]=1;
    for(int i=0; i<n; i++)
    {
        int minv=u;
        int temp = INF;
        //选出离起点最近的点
        for(int j=0; j<n; j++)
        {
            if(visited[j]==0&&lens[j]<temp)
            {
                minv=j;
                temp=lens[j];
            }
        }
        if(minv==u)
            break;
        visited[minv]=1;
        //进行松弛操作
        for(int e = head[minv]; e!=0; e=edges[e].next)
        {
            if(lens[edges[e].v]>lens[minv]+edges[e].len)
            {
                lens[edges[e].v]=lens[minv]+edges[e].len;
            }
        }
    }
}

//存放在优先队列中的数据结构
struct edgeoflist
{
    int v;//边的终点
    int len=INF;//边长
    //重载<运算符,因为c++的优先队列默认是最大堆
    bool operator < (const edgeoflist &x) const {
        return x.len < len;
    }
};

//利用优先队列优化获取相距最近的点的操作,使复杂度降为O(nlogn)
void dijkstra2(int n,int u)
{
    priority_queue<edgeoflist> edgeslist;
    for(int e=head[u]; e!=0; e=edges[e].next)
    {
        lens[edges[e].v]=edges[e].len;
    }
    lens[u]=0;
    edgeoflist e;
    e.v=u;
    e.len=0;
    edgeslist.push(e);
    while(!edgeslist.empty())
    {
        int minv = edgeslist.top().v;
        edgeslist.pop();
        if(visited[minv]==1)
            continue;
        visited[minv]=1;
        for(int e = head[minv]; e!=0; e=edges[e].next)
        {
            if(lens[edges[e].v]>lens[minv]+edges[e].len)
            {
                lens[edges[e].v]=lens[minv]+edges[e].len;
            }
            edgeoflist eg;
            eg.len = lens[edges[e].v];
            eg.v = edges[e].v;
            edgeslist.push(eg);
        }
    }
}
int main()
{
    int n = 5;
    for(int i=0; i<n; i++)
        lens[i]=INF;
    addedge(0,1,5);
    addedge(0,2,2);
    addedge(0,3,6);
    addedge(1,4,1);
    addedge(2,1,1);
    addedge(2,4,5);
    addedge(2,3,3);
    addedge(3,4,2);
    dijkstra2(5,0);
    for(int i=0; i<5; i++)
        cout<<i<<' '<<lens[i]<<endl;
    return 0;
}

结果

以0为起点

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值