最短路算法

来源:互联网 发布:如何看到淘宝追加评论 编辑:程序博客网 时间:2024/06/03 20:15

Dijkstra算法

算法步骤:

a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。

b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。

d.重复步骤b和c直到所有顶点都包含在S中。

例子:

floyd算法

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

 Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点到B,所以,我们假设dist(AB)为节点A到节点B的最短路径的距离,对于每一个节点K,我们检查dist(AK) + dist(KB) < dist(AB)是否成立,如果

成立,证明从A到K再到B的路径比A直接到B的路径短,我们便设置 dist(AB) = dist(AK) + dist(KB),这样一来,当我们遍历完所有节点K,dist(AB)中记录的便是A到B的最短路径的距离。

        很简单吧,代码看起来可能像下面这样:

for (int i=0; i<n; ++i) {
  for (int j=0; j<n; ++j) {
    for (int k=0; k<n; ++k) {
      if (dist[i][k] + dist[k][j] < dist[i][j] ) {
        dist[i][j] = dist[i][k] + dist[k][j];
      }
    }
  }
}


例子:


    #include "stdio.h"
    #include "stdlib.h"
    #include "io.h"
    #include "math.h"
    #include "time.h"

    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    #define MAXEDGE 20
    #define MAXVEX 20
    #define INFINITY 65535

    typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */

    typedef struct
    {
        int vexs[MAXVEX];
        int arc[MAXVEX][MAXVEX];
        int numVertexes, numEdges;
    }MGraph;

    typedef int Patharc[MAXVEX][MAXVEX];
    typedef int ShortPathTable[MAXVEX][MAXVEX];

    /* 构件图 */
    void CreateMGraph(MGraph *G)
    {
        int i, j;

        /* printf("请输入边数和顶点数:"); */
        G->numEdges=16;
        G->numVertexes=9;

        for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
        {
            G->vexs[i]=i;
        }

        for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
        {
            for ( j = 0; j < G->numVertexes; j++)
            {
                if (i==j)
                    G->arc[i][j]=0;
                else
                    G->arc[i][j] = G->arc[j][i] = INFINITY;
            }
        }

        G->arc[0][1]=1;
        G->arc[0][2]=5;
        G->arc[1][2]=3;
        G->arc[1][3]=7;
        G->arc[1][4]=5;

        G->arc[2][4]=1;
        G->arc[2][5]=7;
        G->arc[3][4]=2;
        G->arc[3][6]=3;
        G->arc[4][5]=3;

        G->arc[4][6]=6;
        G->arc[4][7]=9;
        G->arc[5][7]=5;
        G->arc[6][7]=2;
        G->arc[6][8]=7;

        G->arc[7][8]=4;


        for(i = 0; i < G->numVertexes; i++)
        {
            for(j = i; j < G->numVertexes; j++)
            {
                G->arc[j][i] =G->arc[i][j];
            }
        }

    }

    /* Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。 */
    void ShortestPath_Floyd(MGraph G, Patharc *P, ShortPathTable *D)
    {
        int v,w,k;
        for(v=0; v<G.numVertexes; ++v) /* 初始化D与P */
        {
            for(w=0; w<G.numVertexes; ++w)
            {
                (*D)[v][w]=G.arc[v][w];    /* D[v][w]值即为对应点间的权值 */
                (*P)[v][w]=w;                /* 初始化P */
            }
        }
        for(k=0; k<G.numVertexes; ++k)
        {
            for(v=0; v<G.numVertexes; ++v)
            {
                for(w=0; w<G.numVertexes; ++w)
                {
                    if ((*D)[v][w]>(*D)[v][k]+(*D)[k][w])
                    {/* 如果经过下标为k顶点路径比原两点间路径更短 */
                        (*D)[v][w]=(*D)[v][k]+(*D)[k][w];/* 将当前两点间权值设为更小的一个 */
                        (*P)[v][w]=(*P)[v][k];/* 路径设置为经过下标为k的顶点 */
                    }
                }
            }
        }
    }

    int main(void)
    {
        int v,w,k;
        MGraph G;
        
        Patharc P;
        ShortPathTable D; /* 求某点到其余各点的最短路径 */
        
        CreateMGraph(&G);
        
        ShortestPath_Floyd(G,&P,&D);

        printf("各顶点间最短路径如下:\n");
        for(v=0; v<G.numVertexes; ++v)
        {
            for(w=v+1; w<G.numVertexes; w++)
            {
                printf("v%d-v%d weight: %d ",v,w,D[v][w]);
                k=P[v][w];                /* 获得第一个路径顶点下标 */
                printf(" path: %d",v);    /* 打印源点 */
                while(k!=w)                /* 如果路径顶点下标不是终点 */
                {
                    printf(" -> %d",k);    /* 打印路径顶点 */
                    k=P[k][w];            /* 获得下一个路径顶点下标 */
                }
                printf(" -> %d\n",w);    /* 打印终点 */
            }
            printf("\n");
        }

        printf("最短路径D\n");
        for(v=0; v<G.numVertexes; ++v)
        {
            for(w=0; w<G.numVertexes; ++w)
            {
                printf("%d\t",D[v][w]);
            }
            printf("\n");
        }
        printf("最短路径P\n");
        for(v=0; v<G.numVertexes; ++v)
        {
            for(w=0; w<G.numVertexes; ++w)
            {
                printf("%d ",P[v][w]);
            }
            printf("\n");
        }

        return 0;
    }

0 0
原创粉丝点击