最短路径算法

来源:互联网 发布:大数据 5v真实 编辑:程序博客网 时间:2024/06/07 07:28

常见问题:

求小区最短路径、求地铁最短路径、求给出图线之间从一点到另外一点的最短距离、求解所有的最短路径等

思路:

(1)将所有的点转换成Graph;(2)套用Floyd算法或者Dijkstra算法求解出最短路径。

算法实现:

(1)Floyd算法:http://www.cnblogs.com/skywang12345/p/3711523.html

// 邻接矩阵typedef struct _graph{    char vexs[MAX];       // 顶点集合    int vexnum;           // 顶点数    int edgnum;           // 边数    int matrix[MAX][MAX]; // 邻接矩阵}Graph, *PGraph;
/* * floyd最短路径。 * 即,统计图中各个顶点间的最短路径。 * * 参数说明: *        G -- 图 *     path -- 路径。path[i][j]=k表示,"顶点i"到"顶点j"的最短路径会经过顶点k。 *     dist -- 长度数组。即,dist[i][j]=sum表示,"顶点i"到"顶点j"的最短路径的长度是sum。 */void floyd(Graph G, int path[][MAX], int dist[][MAX]){    int i,j,k;    int tmp;    // 初始化    for (i = 0; i < G.vexnum; i++)    {        for (j = 0; j < G.vexnum; j++)        {            dist[i][j] = G.matrix[i][j];    // "顶点i"到"顶点j"的路径长度为"i到j的权值"。            path[i][j] = j;                 // "顶点i"到"顶点j"的最短路径是经过顶点j。        }    }    // 计算最短路径    for (k = 0; k < G.vexnum; k++)    {        for (i = 0; i < G.vexnum; i++)        {            for (j = 0; j < G.vexnum; j++)            {                // 如果经过下标为k顶点路径比原两点间路径更短,则更新dist[i][j]和path[i][j]                tmp = (dist[i][k]==INF || dist[k][j]==INF) ? INF : (dist[i][k] + dist[k][j]);                if (dist[i][j] > tmp)                {                    // "i到j最短路径"对应的值设,为更小的一个(即经过k)                    dist[i][j] = tmp;                    // "i到j最短路径"对应的路径,经过k                    path[i][j] = path[i][k];                }            }        }    }    // 打印floyd最短路径的结果    printf("floyd: \n");    for (i = 0; i < G.vexnum; i++)    {        for (j = 0; j < G.vexnum; j++)            printf("%2d  ", dist[i][j]);        printf("\n");    }}

(2)Dijkstra算法实现:http://www.cnblogs.com/skywang12345/p/3711512.html

// 邻接矩阵typedef struct _graph{    char vexs[MAX];       // 顶点集合    int vexnum;           // 顶点数    int edgnum;           // 边数    int matrix[MAX][MAX]; // 邻接矩阵}Graph, *PGraph;// 边的结构体typedef struct _EdgeData{    char start; // 边的起点    char end;   // 边的终点    int weight; // 边的权重}EData;

  

/* * Dijkstra最短路径。 * 即,统计图(G)中"顶点vs"到其它各个顶点的最短路径。 * * 参数说明: *        G -- 图 *       vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。 *     prev -- 前驱顶点数组。即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。 *     dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。 */void dijkstra(Graph G, int vs, int prev[], int dist[]){    int i,j,k;    int min;    int tmp;    int flag[MAX];      // flag[i]=1表示"顶点vs"到"顶点i"的最短路径已成功获取。    // 初始化    for (i = 0; i < G.vexnum; i++)    {        flag[i] = 0;              // 顶点i的最短路径还没获取到。        prev[i] = 0;              // 顶点i的前驱顶点为0。        dist[i] = G.matrix[vs][i];// 顶点i的最短路径为"顶点vs"到"顶点i"的权。    }    // 对"顶点vs"自身进行初始化    flag[vs] = 1;    dist[vs] = 0;    // 遍历G.vexnum-1次;每次找出一个顶点的最短路径。    for (i = 1; i < G.vexnum; i++)    {        // 寻找当前最小的路径;        // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。        min = INF;        for (j = 0; j < G.vexnum; j++)        {            if (flag[j]==0 && dist[j]<min)            {                min = dist[j];                k = j;            }        }        // 标记"顶点k"为已经获取到最短路径        flag[k] = 1;        // 修正当前最短路径和前驱顶点        // 即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。        for (j = 0; j < G.vexnum; j++)        {            tmp = (G.matrix[k][j]==INF ? INF : (min + G.matrix[k][j])); // 防止溢出            if (flag[j] == 0 && (tmp  < dist[j]) )            {                dist[j] = tmp;                prev[j] = k;            }        }    }    // 打印dijkstra最短路径的结果    printf("dijkstra(%c): \n", G.vexs[vs]);    for (i = 0; i < G.vexnum; i++)        printf("  shortest(%c, %c)=%d\n", G.vexs[vs], G.vexs[i], dist[i]);}
原创粉丝点击