Dijkstra(迪杰斯特拉)算法,计算最短路径

程序小白,希望和大家多交流,共同学习

//迪杰斯特拉(dijkstra)算法,计算最短路径
#include<iostream>
#include<string>
#include<cstdio>
#include<stack>
#define MAX_VN 50
#define INF 23767
using namespace std;

//顶点信息
typedef string VertexData;
//临接矩阵
struct AdjMatrix{
    VertexData vertex[MAX_VN];
    int arcs[MAX_VN][MAX_VN];
    int verNum, arcNum;
};
void createAdjMatrix(AdjMatrix &G);
int locateVertex(AdjMatrix &G, VertexData data);
void outputAdjMatrix(AdjMatrix &G);
//Dijkstra
void dijkstra(AdjMatrix &G);
void dijkstra(const AdjMatrix &G, int v, int *dist, int *pre);
int chooseMin(const AdjMatrix &G, int *dist, bool *mark);
void printDijkstra(const AdjMatrix &G, int v, int *dist, int *pre);

int main(){
/*
6 10
v1 v2 v3 v4 v5 v6
v1 v2 5
v1 v4 7
v2 v3 4
v3 v1 8
v3 v6 9
v4 v3 5
v4 v6 6
v5 v4 5
v6 v1 2
v6 v5 1
*/
    AdjMatrix G;
    createAdjMatrix(G);
    outputAdjMatrix(G);
    dijkstra(G);
    return 0;
}

void createAdjMatrix(AdjMatrix &G){
    cout << "输入顶点个数和弧的条数:";
    cin >> G.verNum >> G.arcNum;
    cout << "输入各个顶点信息:";
    for (int i = 0; i < G.verNum; i++){
        cin >> G.vertex[i];
    }
    cout << "输入各条弧的信息:";
    //初始化各个顶点之间的距离为INF
    for (int i = 0; i < G.verNum; i++){
        for (int j = 0; j < G.verNum; j++){
            G.arcs[i][j] = INF;
        }
    }
    //输入各条弧信息
    VertexData u, v;
    int j, k, w;
    for (int i = 0; i < G.arcNum; i++){
        cin >> u >> v >> w;
        j = locateVertex(G, u);
        k = locateVertex(G, v);
        G.arcs[j][k] = w;
    }
}
int locateVertex(AdjMatrix &G, VertexData data){
    for (int i = 0; i < G.verNum; i++){
        if (G.vertex[i] == data){
            return i;
        }
    }
    return -1;
}
void outputAdjMatrix(AdjMatrix &G){
    for (int i = 0; i < G.verNum; i++){
        for (int j = 0; j < G.verNum; j++){
            if (G.arcs[i][j] == INF){
                cout << "∞ ";
            }
            else
                printf("%-3d", G.arcs[i][j]);
        }
        cout << endl;
    }
}
//Dijkstra
void dijkstra(AdjMatrix &G){
    int n = G.verNum;//顶点个数
    int *dist = new int[n];//用来计算到每个顶点的最短路径
    int *pre = new int[n];//用来标记每个顶点的前驱是谁,也就是到这个点的前一个点(最短路径)

    VertexData data;
    cout << "选择起始点:";
    cin >> data;
    int v = locateVertex(G, data);
    dijkstra(G, v, dist, pre);//找打到各个顶点的最短路径,长度保存在dist中,每个顶点前驱保存在pre中
    printDijkstra(G, v, dist, pre);//根据长度和pre打印到各个顶点的路径状况
    delete []dist;
    delete []pre;
}
void dijkstra(const AdjMatrix &G, int v, int *dist, int *pre){
    cout << "dijkstra\n";
    int n = G.verNum;
    //mark用来记录每个顶点书否已经在最短路径中
    bool *mark = new bool[n];
    //初始化各个信息,dist为了 保存最短路径,所以设置为最大值
    //前驱未定,设置为-1,所有顶点未标记
    for (int i = 0; i < n; i++){
        dist[i] = INF;
        pre[i] = -1;
        mark[i] = false;
    }

    //根据已有的起始点标记一些值
    dist[v] = 0;
    mark[v] = true;
    for (int i = 0; i < n; i++){
        if (G.arcs[v][i] != INF){
            dist[i] = G.arcs[v][i];//目前,是第一个点,所有可以到达v的顶点的最短路径值,就是已有的权值
            pre[i] = v;//当然可以到这些点的前驱就是顶点v
        }
    }
    //接下来要把其他的顶点的信息,在dist和pre中进行标记
    for (int i = 1; i < n; i++){
        int m = chooseMin(G, dist, mark);//找出dist中的最小值,实际上是找到邻接点的最小值
        //cout << m << endl;
        if(m != -1){
            mark[m] = true;
            for (int j = 0; j < n; j++){//最小值加上最小值顶点的邻接点的权值小于dist中的记录
                                        //就需要更新dist此时的状况是走多的结点,但是权值总和最少
                                        //当然此时结点的前驱结点就改变了
                if (!mark[j] && dist[m] + G.arcs[m][j] < dist[j]){
                    dist[j] = dist[m] + G.arcs[m][j];
                    pre[j] = m;
                }
            }
        }
    }
    delete []mark;
}
int chooseMin(const AdjMatrix &G, int *dist, bool *mark){
    int n = G.verNum, k, min = INF;
    for (int i = 0; i < n; i++){
        if (!mark[i] && dist[i] < min){//在未标记的顶点中找到最小值对应的顶点
            k = i;
            min = dist[i];
        }
    }

    if (min < INF){
        return k;
    }
    return -1;//没有最小值返回-1
}
//打印Dijkstra
//此时已知没有被更新的顶点是起始点和终止点,pre都为-1
//因为pre中存的都是前驱,所以将它的前驱顺次保存在栈中,在从栈顶顺次输出,就是最短路径了
void printDijkstra(const AdjMatrix &G, int v, int *dist, int *pre){
    cout << "print\n";
    stack<int> s;
    int n = G.verNum;
    for (int i = 0; i < n; i++){
        if (i != v){
            //将顶点i的前驱顺次入栈
            s.push(i);
            int t = pre[i];
            while (t != -1){
                s.push(t);
                t = pre[t];
            }
            //现在出栈
            int h = s.top();
            s.pop();
            cout << G.vertex[h];
            while (!s.empty()){
                h = s.top();
                s.pop();
                cout << " --> " << G.vertex[h]; 
            }
            if (dist[i] != INF){
                cout << " : " << dist[i] << endl;
            }
            else
                cout << " can't reached" << endl;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/cheng_cuo_tuo/article/details/80578269