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

单源最短路径算法 dijkstra
数据结构与算法C++之单源最短路径算法 dijkstra_第1张图片
数据结构与算法C++之单源最短路径算法 dijkstra_第2张图片
数据结构与算法C++之单源最短路径算法 dijkstra_第3张图片
在这里插入图片描述
数据结构与算法C++之单源最短路径算法 dijkstra_第4张图片
(1)从起始节点0开始,与0连接的节点有1,2,3,将它们的权重存入右表中,可以看出最小的权重是边0-2,权重为2,那么在图中不能有负权边的前提下,0-2的最短路径就是边0-2
数据结构与算法C++之单源最短路径算法 dijkstra_第5张图片
(2)接下来,以节点2为出发点,考察与2连接的节点1,4,3,边2-1的权重为1,那么0-2-1的耗费为3,比上图表中0-1的耗费5要小,所以将1位置的5替换为3;边2-4权重为5,表中没有4的耗费,那么0-2-4的耗费7填入表中;边2-3权重为3,那么0-2-3耗费为5,比表中0-3的耗费6要小,那么将上图表中3对应的耗费6改为耗费5,如下图
数据结构与算法C++之单源最短路径算法 dijkstra_第6张图片
(3)在上面的基础上,我们可以确定0到1最短的路径是0-2-1,耗费为3,因此节点1也确定下来了,标记为蓝色,表格中节点1对应的耗费3标为红色
数据结构与算法C++之单源最短路径算法 dijkstra_第7张图片
(4)此时节点2的邻边都遍历完了,确定了节点1为最短路径,此时将节点1固定住,将节点1作为出发点,节点1的邻边只有一个4, 0-2-1-4的耗费为4,比原来的7小,所以将7替换为4,此时节点1的邻边都遍历完了,确定节点4为最短路径,标记为蓝色,表格中节点4对应的耗费4标红
数据结构与算法C++之单源最短路径算法 dijkstra_第8张图片
(5)此时节点4没有相邻的节点,剩下的节点3也没有别的选择了,0-2-3就是最短路径,如下图
数据结构与算法C++之单源最短路径算法 dijkstra_第9张图片
程序实现如下

#include 
#include "SparseGraph.h"
#include "ReadGraph.h"
#include "Dijkstra.h"

using namespace std;

int main()
{
    string filename = "testG1.txt";
    int V = 5;

    SparseGraph<int> g = SparseGraph<int>(V, true);
    ReadGraph<SparseGraph<int>, int> readGraph( g, filename );

    cout<<"Test Dijkstra:"<<endl<<endl;
    Dijkstra<SparseGraph<int>, int> dij(g, 0);
    for( int i = 1; i < V; i ++){
        cout<<"Shortest Path to "<<i<<" : "<<dij.shortestPathTo(i)<<endl;
        dij.showPath(i);
        cout<<"---------"<<endl;
    }

    return 0;
}

Dijkstra.h

#include 
#include 
#include 

#ifndef _EDGE_H_
#define _EDGE_H_
#include "Edge.h"
#endif

#ifndef _INDEXMINHEAP_H_
#define _INDEXMINHEAP_H_
#include "IndexMinHeap.h"
#endif

using namespace std;

template<typename Graph, typename Weight>
class Dijkstra{

private:
    Graph &G;
    int s;

    Weight *distTo;
    bool *marked;
    vector< Edge<Weight>* > from;

public:
    Dijkstra(Graph &graph, int s):G(graph){
        this->s = s;
        distTo = new Weight[G.V()];
        marked = new bool[G.V()];
        for ( int i = 0; i < G.V(); i ++){
            distTo[i] = Weight();
            marked[i] = false;
            from.push_back(NULL);
        }

        IndexMinHeap<Weight> ipq(G.V());

        // Dijkstra
        distTo[s] = Weight();
        ipq.insert( s, distTo[s] );
        marked[s] = true;

        while ( !ipq.isEmpty() ){

            int v = ipq.extractMinIndex();

            //distTo[v] 就是s到v的最短距离
            marked[v] = true;

            typename Graph::adjIterator adj(G, v);
            for( Edge<Weight>* e = adj.begin(); !adj.end(); e = adj.next() ){
                int w = e->other(v);
                if ( !marked[w] ){
                    if ( from[w] == NULL || distTo[v] + e->wt() < distTo[w] ){
                        distTo[w] = distTo[v] + e->wt();
                        from[w] = e;
                        if ( ipq.contain(w) )
                            ipq.change( w, distTo[w] );
                        else
                            ipq.insert( w, distTo[w]);
                    }
                }
            }
        }
    }

    ~Dijkstra(){
        delete[] distTo;
        delete[] marked;
    }

    Weight shortestPathTo( int w ){
        assert( w >= 0 && w < G.V() );
        return distTo[w];
    }

    bool hasPathTo( int w ){
        assert( w >= 0 && w < G.V() );
        return marked[w];
    }

    void shortestPath( int w, vector< Edge<Weight> > &vec){
        assert( w >= 0 && w < G.V() );

        stack< Edge<Weight>* > s;
        Edge<Weight> *e = from[w];

        while( e->v() != this->s ){
            s.push(e);
            e = from[e->v()];
        }
        s.push(e);

        while( !s.empty() ){
            e = s.top();
            vec.push_back( *e );
            s.pop();
        }
    }

    void showPath( int w ){
        assert( w >= 0 && w < G.V() );

        vector< Edge<Weight> > vec;
        shortestPath(w, vec);
        for ( int i = 0; i < vec.size(); i ++ ){
            cout<<vec[i].v()<<" -> ";
            if ( i == vec.size() - 1 )
                cout<<vec[i].w()<<endl;
        }
    }
};

其他的函数见上几篇博客

testG1.txt 为

5 8
0 1 5
0 2 2
0 3 6
1 4 1
2 1 1
2 4 5
2 3 3
3 4 2

输出为
数据结构与算法C++之单源最短路径算法 dijkstra_第10张图片

你可能感兴趣的:(数据结构与算法)