初学图论-Dijkstra单源最短路径算法

当图中所有边的权重为非负值时,我们可以选用巧妙Dijkstra算法。

本文使用C++实现了这一基本算法。参考《算法导论》第24.3节。

不过在算法的实现中,取当前与原点s最近的节点操作时,采用了线性扫描的策略。如果换用堆或者优先级队列会好很多。

/**
 * Dijkstra‘s Single Source Shortest Path Algorithm in C++
 * Time Cost : O(N^2)
 * Thanks to Introduction to Algorithms (CLRS) Chapter 24.3
 * Author: Zheng Chen / Arclabs001
 * Copyright 2015 Xi‘an University of Posts & Telecommunications
 */
#include <iostream>
#include <vector>
#include <stack>
#include <fstream>
#define INF 0xfffffff
using namespace std;
const int N = 5;
const int M = 10;
ifstream in;

enum status {UNSELECTED,SELECTED};

struct edge
{
    int dest;
    int weight;
};

struct vertex
{
    int num;
    int dist;
    int inDegree,outDegree;
    status _stat;
    vertex * parent;
}V[N];

vector<edge> AdjList[N];
vector<int> SELECTED_vertex;

void initialize(int s)
{
    for(int i=0; i<N; i++)
    {
        V[i].num = i;
        V[i].dist = INF;
        V[i].parent = nullptr;
        V[i].inDegree = 0;
        V[i].outDegree = 0;
        V[i]._stat = UNSELECTED;
        AdjList[i].clear();
    }

    for(int i=0; i<M; i++)  //Read informations of edges and insert into the Adjacent List
    {
        int _start, _dest, _weight;
        edge * tmp = new edge;

        in>>_start>>_dest>>_weight;
        tmp->dest = _dest;
        tmp->weight = _weight;
        V[_start].outDegree++;
        V[_dest].inDegree++;

        AdjList[_start].push_back(*tmp);
    }

    V[s].dist = 0;
    SELECTED_vertex.clear();
}

void relax(int u, int v, int weight)  //The "relax" operation
{
    if(V[v].dist > V[u].dist + weight)
    {
        V[v].dist = V[u].dist + weight;
        V[v].parent = &V[u];
    }
}

void print_path(vertex *s, vertex *v)
{
    if(v == s)
        cout<<s->num;
    else if(v->parent == nullptr)
        cout<<"No path from "<<s->num<<" to "<<v->num<<endl;
    else
    {
        print_path(s,v->parent);
        cout<<"->"<<v->num;
    }
}

//Get the nearest vertex to the set of selected vertices 
//Actually, this linear scan costed so much than I expected.
//Using a heap can make the time cost better
int get_nearest_vertex()  
{
    int _dist = INF;
    int nearest;
    for(int i=0;i<N;i++)
    {
        if(V[i].dist < _dist && V[i]._stat == UNSELECTED)
        {
            _dist = V[i].dist;
            nearest = i;
        }
    }
    return nearest;
}

void Dijkstra(int s)  //The main function of Dijkstra algorithm
{
    initialize(s);
    int numof_UNSELECTED = N-1;
    while(numof_UNSELECTED != 0)
    {
        int u = get_nearest_vertex();
        SELECTED_vertex.push_back(u);

        edge tmp;
        for(int j=0; j<V[u].outDegree; j++)
        {
            tmp = AdjList[u][j];
            relax(u,tmp.dest,tmp.weight);
        }

        V[u]._stat = SELECTED;
        numof_UNSELECTED--;
    }
}

int main()
{
    in.open("Dijkstra.txt");
    int s = 0;
    Dijkstra(s);

    cout<<"Succeed ! The distance of each vertex are :"<<endl;
    for(int i=0; i<N; i++)
        if(V[i].dist == INF)
            cout<<"INF ";
        else
            cout<<V[i].dist<<" ";

    cout<<endl<<"One of the shortest path is :"<<endl;
    print_path(&V[0],&V[4]);
    return 0;
}

/*
Pseudo Code :
Dijkstra(G,w,s)
    S = empty set
    Q = G.V - s
    while Q != empty set
        u = EXTRACT-MIN(Q)
        S = S ∪ u
        for each vertex v in AdjList[u]
            relax(u,v,w)
 */

//Dijkstra.txt文件内容如下:

0 1 10

0 3 5

1 2 1

1 3 2

2 4 4

3 1 3

3 2 9

3 4 2

4 0 7

4 2 6

每一行的三个元素分别表示某条边的起始节点、终止节点、这条边的权重。

时间: 2024-10-16 19:43:13

初学图论-Dijkstra单源最短路径算法的相关文章

初学图论-Dijkstra单源最短路径算法基于优先级队列(Priority Queue)的实现

这一次,笔者使用了STL库中的优先级队列(Priority Queue)来完成Dijkstra算法中extract-min()语句(即从未选中的节点中选取一个距离原点s最小的点)的功能.由于优先级队列的插入.删除操作只需要logn的时间花费,因此降低了不少运行时间. 本文使用C++实现了这一基本算法.参考<算法导论>第24.3节. /**  * Dijkstra's Single Source Shortest Path Algorithm in C++  * Time Cost : O(Ml

Dijkstra 单源最短路径算法

Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年构思并于 1959 年发表.其解决的问题是:给定图 G 和源顶点 v,找到从 v 至图中所有顶点的最短路径. Dijkstra 算法采用贪心算法(Greedy Algorithm)范式进行设计.在最短路径问题中,对于带权有向图 G = (V, E),Dijkstra 算法的初始实现版本未使用最小优先

Bellman-Ford 单源最短路径算法

Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Lester Ford 分别发表于 1958 年和 1956 年,而实际上 Edward F. Moore 也在 1957 年发布了相同的算法,因此,此算法也常被称为 Bellman-Ford-Moore 算法. Bellman-Ford 算法和 Dijkstra 算法同为解决单源最短路径的算法.对于带权有向

单源最短路径算法---Dijkstra

Dijkstra算法树解决有向图G=(V,E)上带权的单源最短路径问题,但是要求所有边的权值非负. 解题思路: V表示有向图的所有顶点集合,S表示那么一些顶点结合,从源点s到该集合中的顶点的最终最短路径的权值(程序中用dist[i]表示)已经确定.算法反复选择具有最短路径估计的顶点u 属于 V-S(即未确定最短路径的点,程序中finish[i]=false的点),并将u加入到S中(用finish[i]=true表示),最后对u的所有输出边进行松弛. 程序实现:      输入数据: 5 7 0

带负权图的单源最短路径算法:Bellman-Ford算法

算法简介 前面介绍过图的单源最短路径算法Dijkstra算法,然而Dijkstra算法无法判断含负权边的图的最短路.如果遇到负权,在没有负权回路存在时(负权回路的含义是,回路的权值和为负.)即便有负权的边,也可以采用Bellman-Ford算法正确求出最短路径. Bellman-Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数 w是 边集 E 的映射.对图G运行Bellman-Ford算法的结果是一个布尔值,表

Dijkstra单源最短路径

Dijkstra单源最短路径 给定一个带权有向图G=(V,E) ,其中每条边的权是一个非负实数.另外,还给定 V 中的一个顶点,称为源.现在我们要计算从源到所有其他各顶点的最短路径长度.这里的长度是指路上各边权之和.这个问题通常称为单源最短路径问题. 下面给出两个计算单源最短路径的模板. Dijkstra_简化版:时间复杂度O(n^2),不可处理重边图 //计算图的以s点为起点的单源最短路径 //图中节点从1到n编号 //运行dijkstrea之前,需要先把图中两点间的距离保存在dist[i][

SPFA算法-单源最短路径算法

1.介绍: SPFA算法:单源最短路径算法,一种高效的最短路径算法! 2.思路 (1)初始化 1>源点路径为0  :d[s]=0 ,其中s为源点 2>初始化d[N]为无穷大,即d[i]表示,源点s到i为无穷大INF 3>p[N]初始化为源点s或-1,表示没有前驱 (2)队列+松弛 1>读取队头顶点u,并将队头顶点u出队(记得消除标记): 2>将与点u相连的所有点v进行松弛操作,如果能更新估计值(即令d[v]变小),那么就更新; 3>另外,如果点v没有在队列中,那么要将点

Dijkstra算法详细(单源最短路径算法)

介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或许,你曾经感觉它很难,那么,这个时候正适合你重新认识它. Dijkstra能是干啥的? Dijkstra是用来求单源最短路径的 就拿上图来说,假如直到的路径和长度已知,那么可以使用dijkstra算法计算南京到图中所有节点的最短距离. 单源什么意思? 从一个顶点出发,Dijkstra算法只能求一个顶

数据结构与算法--单源最短路径算法之dijkstra

单源最短路径之dijkstra算法 最优子问题:dis(s,...,e)是s到e的最短路径,在这条路径上的所有点之间dis(pi,pj)距离是最小的. 算法思路: 首先初始化,dis[s][i]是s到i的距离,直接相连的就是其距离,不直接相连的就是无穷大 下面是算法主要模块: 1.选取dis[i]最小的点加入到P{S}中, 2.计算是否更新dis[j],j是和i直接相连的 3.重复以上步骤,直到e