迪杰斯特拉算法求最短路

迪杰斯特拉(Dijkstra)

迪杰斯特拉提出了一个按路径长度递增的次序产生最短路径的算法,其实这也是一个贪心的过程,,,,

算法步骤:

首先要明白三个数组:
bool s[MAXN]; //记录从源点v0到终点vi是否已被确认最短路径长度
int path[MAXN]; //记录从源点v0到终点vi的当前直接前驱顶点序号
int D[MAXN]; //记录从源点v0到终点v1的当前最短路径

所以说,s[i]原来判断,path[i]原来查找路径,D[i]中存最短路。

1、初始时,S 只包含源点,即 S={v},v 的距离为 0。U 包含除 v 外的其他顶点,即:U={其余顶点},若 v 与 U 中顶点 u 有边,则 正常有权值,若 u 不是 v 的邻接点,则 权值为 ∞。
2、从 U 中选取一个距离 v 最小的顶点 k,把 k加入 S 中(该选定的距离就是 v 到 k 的最短路径长度)。
3、以 k 为新考虑的中间点,修改 U 中各顶点的距离;若从源点v 到顶点 u 的距离(经过顶点 k)比原来距离(不经过顶点k)短,则修改顶点 u 的距离值,修改后的距离值的顶点 k 的距离加上边上的权。
4、重复步骤 2 和 3 直到所有顶点都包含在 S 中。


迪杰斯特拉算法求最短路_第1张图片

样例输出:

迪杰斯特拉算法求最短路_第2张图片
代码块:

//#include
#include
#include
#include
#include
#include
using namespace std ;
typedef long long ll;
#define MAXN 105
#define INF 0x3f3f3f3f
#define MALL (Bithrnode *)malloc(sizeof(Bithrnode));

bool s[MAXN];                   //记录从源点v0到终点vi是否已被确认最短路径长度
int path[MAXN];                 //记录从源点v0到终点vi的当前直接前驱顶点序号
int D[MAXN];                    //记录从源点v0到终点v1的当前最短路径
typedef struct
{
    int vexs[MAXN];            //顶点表
    int arcs[MAXN][MAXN];      //邻接矩阵
    int vexnum, arcnum;        //图的当前点数和边数
} AMGraph;

void init(AMGraph &G)
{
    cout << "请输入顶点数vex和边数arc:" << '\n';
    cin >> G.vexnum >> G.arcnum;              //输入点数和边数
    cout << "请依次输入各个顶点的代号(可以用int, char和string)" << '\n';
    for(int i=0; i<G.vexnum; ++i)
        cin >> G.vexs[i];
    for(int i=0; i<G.vexnum; ++i)          //初始化矩阵,边的权值为无穷大INF
        for(int j=0; j<G.vexnum; ++j)
            G.arcs[i][j] = INF;
    cout << "请输入arc条边与边的关系" << '\n';
    for(int k=0; k<G.arcnum; ++k)
    {
        int u, v, len, i, j;
        cin >> u >> v >> len;
        for(int c=0; c<G.vexnum; ++c)       //查找u、v在顶点集中的位置
        {
            if(G.vexs[c] == u)
                i = c;
            if(G.vexs[c] == v)
                j = c;
        }
        G.arcs[i][j] = len;                //有向图
//      G.arcs[j][i] = len;
    }
}

void Dijkstra(AMGraph G, int v0)
{
    //用Dijkstra算法求有向图G的v0顶点到其余顶点的最短路径
    int n = G.vexnum;
    for(int i=0; i<n; ++i)                  //初始化n个顶点
    {
        s[i] = false;
        D[i] = G.arcs[v0][i];               //将v0到各个终点的最短路径长度初始化为其弧的权值
        if(D[i] < INF)                      //如果v0和i之间有弧,则将i的前驱置为v0
            path[i] = v0;
        else                                //如果v0和i之间无弧,则置为-1;
            path[i] = -1;
    }
    s[v0] = true;                           //将v0加入s,
    D[v0] = 0;

    for(int i=1; i<n; ++i)                  //检索其余的n-1个顶点
    {
        int minn = INF, x;
        for(int j=0; j<n; ++j)
        {
            if(!s[j] && D[j] < minn)
            {
                x = j;
                minn = D[j];
            }
        }
        s[x] = true;
        for(int j=0; j<n; ++j)
        {
            if(!s[j] && D[x] + G.arcs[x][j] < D[j])
            {
                D[j] = D[x] + G.arcs[x][j];
                path[j] = x;
            }
        }
    }
}

void print(int n)
{
    for(int i=1; i<n; ++i)
        if(D[i] < INF)
            printf("v0->v%d: %d\n", i, D[i]);
        else
           printf("v0->v%d: 不可通行\n", i);
}

int main()
{
    AMGraph G;
    init(G);
    Dijkstra(G, 0);
    print(G.vexnum);
}

Dijkstra:

void Dijkstra(AMGraph G, int v0)
{
    //用Dijkstra算法求有向图G的v0顶点到其余顶点的最短路径
    int n = G.vexnum;
    for(int i=0; i<n; ++i)                  //初始化n个顶点
    {
        s[i] = false;
        D[i] = G.arcs[v0][i];               //将v0到各个终点的最短路径长度初始化为其弧的权值
        if(D[i] < INF)                      //如果v0和i之间有弧,则将i的前驱置为v0
            path[i] = v0;
        else                                //如果v0和i之间无弧,则置为-1;
            path[i] = -1;
    }
    s[v0] = true;                           //将v0加入s,
    D[v0] = 0;

    for(int i=1; i<n; ++i)                  //检索其余的n-1个顶点
    {
        int minn = INF, x;
        for(int j=0; j<n; ++j)
        {
            if(!s[j] && D[j] < minn)	   //选择一条当前的最短路径,终点为x
            {
                x = j;
                minn = D[j];
            }
        }
        s[x] = true;						//将x加入S中
        for(int j=0; j<n; ++j)
        {
            if(!s[j] && D[x] + G.arcs[x][j] < D[j])
            {
                D[j] = D[x] + G.arcs[x][j];	//更新D[j]
                path[j] = x;				//更新j的前驱为x
            }
        }
    }
}

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