単一ソース最短パス-Dijkstraアルゴリズム(C++)

10544 ワード

最近図のアルゴリズムを復習して、手を練習してまずDijkstraアルゴリズムを持って刀を切りましょう
以下はC++コード
含む:Dijkstraアルゴリズム関数(ソースノードから残りのノードまでの最短パスを返す)、パス印刷出力関数
PS:私はvectorを使うのが好きで、原生配列を使うのが好きではありません;stringだけが好きで、char*、char[]なんてめちゃくちゃなのが好きではありません.
#include 
#include 

using namespace std;

typedef int DATA_TYPE;  //    int 
const DATA_TYPE NO_EDGE = 10000000;  //       

//        
struct MatrixGraph
{
    vector<vector > weights;
    int vertexNum;  //          ,      
};

//       (            )
vector<int> getVisitPath(vector<int> path, int startNode, int endNode)
{
    vector<int> visitPath;
    visitPath.push_back(endNode);

    if (path[endNode] != -1)
    {
        while (path[endNode] != startNode)
        {
            visitPath.insert(visitPath.begin(), path[endNode]);
            endNode = path[endNode];
        }
    }

    visitPath.insert(visitPath.begin(), startNode);
    return visitPath;
}

//         
void displayPath(vector distance, vector<int> path, int startNode)
{
    for (size_t i = 0; i < path.size(); ++i)
    {
        //                  
        if (i != startNode && distance[i] < NO_EDGE)
        {
            vector<int> visitPath = getVisitPath(path, startNode, i);
            cout << "From " << visitPath[0] << " to " << visitPath[visitPath.size() - 1] << "||  ";
            cout << "Distance: " << distance[i] << "  ||  Path:  ";

            for (size_t j = 0; j < visitPath.size() - 1; ++j)
            {
                cout << visitPath[j] << "->";
            }
            cout << visitPath[visitPath.size() - 1] << endl;
        }

    }
}

// Dijkstra  
vector dijkstra(vector<vector > weights, int startNode)
{
    vector distance;  //                   
    vector<int> path;  //     (  )
    vector<int> S;  //     
    DATA_TYPE minDistance;  //         

    int vertexNum = weights.size();

    for (size_t i = 0; i < vertexNum; ++i)
    {
        //        
        distance.push_back(weights[startNode][i]);
        //           
        S.push_back(0);  // 0     

        //      
        if (weights[startNode][i] != NO_EDGE)
            path.push_back(startNode);  //   
        else
            path.push_back(-1);  //      -1
    }

    S[startNode] = 1;  //      S 
    path[startNode] = startNode;  //      startNode      

    size_t k;  //     

    for (size_t i = 0; i < vertexNum; ++i)
    {
        minDistance = NO_EDGE;
        for (size_t j = 0; j < vertexNum; ++j)
        {
            if ((S[j] == 0) && (distance[j] < minDistance))
            {
                k = j;
                minDistance = distance[j];
            }
        }
        S[k] = 1;  //        k  S

        for (size_t j = 0; j < vertexNum; ++j)
        {
            if (S[j] == 0)
            {
                //      k     (   k      )
                if ((weights[k][j] < NO_EDGE) && (distance[k] + weights[k][j] < distance[j]))
                {
                    //                  ,   
                    distance[j] = distance[k] + weights[k][j];
                    path[j] = k;  //   k    
                }
            }
        }
    }

    //       
    displayPath(distance, path, startNode);

    return distance;
}


int main() {

    //      
    //         0        (   ,   )
    //      
    MatrixGraph graph;
    graph.vertexNum = 7;  //              
    graph.weights.push_back(vector{0, 4, 6, 6, NO_EDGE, NO_EDGE, NO_EDGE});
    graph.weights.push_back(vector{NO_EDGE, 0, 1, NO_EDGE, 7, NO_EDGE, NO_EDGE});
    graph.weights.push_back(vector{NO_EDGE, NO_EDGE, 0, NO_EDGE, 6, 4, NO_EDGE});
    graph.weights.push_back(vector{NO_EDGE, NO_EDGE, 2, 0, NO_EDGE, 5, NO_EDGE});
    graph.weights.push_back(vector{NO_EDGE, NO_EDGE, NO_EDGE, NO_EDGE, 0, NO_EDGE, 6});
    graph.weights.push_back(vector{NO_EDGE, NO_EDGE, NO_EDGE, NO_EDGE, 1, 0, 8});
    graph.weights.push_back(vector{NO_EDGE, NO_EDGE, NO_EDGE, NO_EDGE, NO_EDGE, NO_EDGE, 0});

    vector distance = dijkstra(graph.weights, 1);

    return 0;
}

試験用例図は以下の通りである.
コンパイル環境(CLion 2016 with MinGW G+,GDB 7.11)
出力結果:From 1 to 2‖Distance:1‖Path:1−>2 FFrom 1 to 4‖Distance:6‖Path:1−>2−>5−>4 From 1 to 5‖Distance:5‖Path:1−>2−>5 From 1 to 6‖Distance:12‖Path:1−>2−>5−>4−>6