Dijkstra算法及其优化(Dijkstra+heap)

Dijkstra(迪杰斯特拉)算法是一种经典的求单源最短路的算法,大体上就是利用已经找到的点的最短路去推其他点的最短路。

我们先将图中的点分为两部分:

S:已经找到最短路的点

T:图G - S,剩下的点

具体过程如下:

  • 将dis数组初始化为INF,源点s,dis[s] = 0,s点加入S集,s点为当前点
  • 重复以下步骤:
  • 遍历当前点的子点,如果当前点的子点dis值 > dis[当前点]+其之间边的边权,将子点dis值更新为dis[当前点]+其之间边的边权
  • 在T集中找出一个dis值最小的点移入S集,并将其作为当前点
  • 直到T集为空时,结束

经过上述步骤之后,dis数组内的值便是每一点到源点的最短路值。

示例代码(kuangbin模板):

const int MAXN=1010;
#define typec int
const typec INF=0x3f3f3f3f;//防止后面溢出,这个不能太大
bool vis[MAXN];
int pre[MAXN];
void Dijkstra(typec cost[][MAXN], typec lowcost[], int n,int beg){
    for(int i=0;i<n;i++){
        lowcost[i]=INF; vis[i]=false; pre[i]=−1;
    }
    lowcost[beg]=0;
    for(int j=0;j<n;j++){
        int k=−1;
        int Min=INF;
        for(int i=0;i<n;i++)
            if(!vis[i]&&lowcost[i]<Min){
                Min=lowcost[i];
                k=i;
            }
        if(k==−1)break;
        vis[k]=true;
        for(int i=0;i<n;i++)
            if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i]){
                lowcost[i]=lowcost[k]+cost[k][i];
                pre[i]=k;
            }
    }
}

算法中每次寻找T集中dis值最小的点的复杂度为O(n),我们可以用堆(heap)来优化这一过程,使其复杂度降到O(logn),这样总体复杂度降到O(nlogn)。

示例代码(kuangbin模板):

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));
}
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以,以下是一个使用堆优化Dijkstra 算法的 C 代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <limits.h> #define MAX_VERTICES 10000 #define INF INT_MAX typedef struct { int v; int w; } Edge; typedef struct { Edge* edges[MAX_VERTICES]; int edge_count[MAX_VERTICES]; int vertex_count; } Graph; typedef struct { int* heap; int* indices; int* dist; int size; } Heap; Graph* create_graph(int vertex_count) { Graph* graph = (Graph*) malloc(sizeof(Graph)); graph->vertex_count = vertex_count; for (int i = 0; i < vertex_count; i++) { graph->edges[i] = (Edge*) malloc(sizeof(Edge) * vertex_count); graph->edge_count[i] = 0; } return graph; } void add_edge(Graph* graph, int u, int v, int w) { Edge edge = {v, w}; graph->edges[u][graph->edge_count[u]++] = edge; } Heap* create_heap(int size) { Heap* heap = (Heap*) malloc(sizeof(Heap)); heap->heap = (int*) malloc(sizeof(int) * size); heap->indices = (int*) malloc(sizeof(int) * size); heap->dist = (int*) malloc(sizeof(int) * size); heap->size = 0; return heap; } void heap_swap(Heap* heap, int i, int j) { int temp = heap->heap[i]; heap->heap[i] = heap->heap[j]; heap->heap[j] = temp; heap->indices[heap->heap[i]] = i; heap->indices[heap->heap[j]] = j; } void heap_push(Heap* heap, int v, int dist) { heap->heap[heap->size] = v; heap->indices[v] = heap->size; heap->dist[v] = dist; int i = heap->size++; while (i > 0) { int p = (i - 1) / 2; if (heap->dist[heap->heap[i]] < heap->dist[heap->heap[p]]) { heap_swap(heap, i, p); i = p; } else { break; } } } int heap_pop(Heap* heap) { int v = heap->heap[0]; heap->indices[v] = -1; heap->heap[0] = heap->heap[--heap->size]; heap->indices[heap->heap[0]] = 0; int i = 0; while (i * 2 + 1 < heap->size) { int l = i * 2 + 1; int r = i * 2 + 2; int j = l; if (r < heap->size && heap->dist[heap->heap[r]] < heap->dist[heap->heap[l]]) { j = r; } if (heap->dist[heap->heap[j]] < heap->dist[heap->heap[i]]) { heap_swap(heap, i, j); i = j; } else { break; } } return v; } void dijkstra(Graph* graph, int s, int* dist) { Heap* heap = create_heap(graph->vertex_count); for (int i = 0; i < graph->vertex_count; i++) { dist[i] = INF; } dist[s] = 0; heap_push(heap, s, 0); while (heap->size > 0) { int u = heap_pop(heap); for (int i = 0; i < graph->edge_count[u]; i++) { int v = graph->edges[u][i].v; int w = graph->edges[u][i].w; if (dist[u] + w < dist[v]) { dist[v] = dist[u] + w; if (heap->indices[v] >= 0) { heap_push(heap, v, dist[v]); } else { heap_push(heap, v, dist[v]); } } } } } int main() { int n, m, s; scanf("%d%d%d", &n, &m, &s); Graph* graph = create_graph(n); for (int i = 0; i < m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); add_edge(graph, u - 1, v - 1, w); } int dist[MAX_VERTICES]; dijkstra(graph, s - 1, dist); for (int i = 0; i < n; i++) { if (dist[i] == INF) { printf("INF\n"); } else { printf("%d\n", dist[i]); } } return 0; } ``` 希望这个代码能够帮助你理解 Dijkstra 算法的堆优化实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值