数据结构与算法--最短路径

168 阅读5分钟

1、最短路路径-Dijkstra 算法

#define OK        1
#define ERROR     0
#define TRUE      1
#define FALSE     0

#define MAXEDGE   20
#define MAXVEX    20
#define INFINITYC 65535

typedef int Status;
typedef struct {
    int vexs[MAXVEX];
    int arc[MAXVEX][MAXVEX];
    int numVertexes, numEdges;
}MGraph;
typedef int Patharc[MAXVEX][MAXVEX];
typedef int ShortPathTable[MAXVEX][MAXVEX];
/* 求得网图中2点间最短路径
 Dijkstra 算法
 G: 网图;
 v0: V0开始的顶点;
 p[v]: 前驱顶点下标;
 D[v]: 表示从V0到V的最短路径长度和;
 */
void ShortestPath_Dijkstra(MGraph G, int v0, Patharc *P, ShortPathTable *D)
{
    int v, w, k, min;
    k = 0;
    /*final[w] = 1 表示求得顶点V0~Vw的最短路径*/
    int final[MAXVEX];

    /*1.初始化数据*/
    for (v = 0; v < G.numVertexes; v++) {
        //全部顶点初始化为未知最短路径状态0
        final[v] = 0;
        //将与V0 点有连线的顶点最短路径值;
        (*D)[v] = G.arc[v0][v];
        //初始化路径数组p = 0;
        (*P)[v] = 0;
    }

    //V0到V0的路径为0
    (*D)[v0] = 0;
    //V0到V0 是没有路径的.
    final[v0] = 1;
    //v0到V0是没有路径的
    (*P)[v0] = -1;

    //2. 开始主循环,每次求得V0到某个顶点的最短路径
    for (v = 1; v < G.numVertexes; v++) {
        //当前所知距离V0顶点最近的距离
        min = INFINITYC;
        /*3.寻找离V0最近的顶点*/
        for (w = 0; w < G.numVertexes; w++) {
            if (!final[w] && (*D)[w] < min) {
                k = w;
                //w顶点距离V0顶点更近
                min = (*D)[w];
            }
        }

        //将目前找到最近的顶点置为1;
        final[k] = 1;

        /*4.把刚刚找到v0到v1最短路径的基础上,对于v1 与 其他顶点的边进行计算,得到v0与它们的当前最短距离;*/
        for (w = 0; w < G.numVertexes; w++) {
            //如果经过v顶点的路径比现在这条路径长度短,则更新
            if (!final[w] && (min + G.arc[k][w] < (*D)[w])) {
                //找到更短路径, 则修改D[W],P[W]
                //修改当前路径的长度
                (*D)[w] = min + G.arc[k][w];
                (*P)[w] = k;
            }
        }
    }
}

swift

struct MGraph {
    var arc: Array<Array<Int>> = Array<Array<Int>>()
    var numNodes: Int = 0, numEdges: Int = 0
    /* 2 求得网图中2点间最短路径
     Dijkstra 算法
     G: 网图;
     v0: V0开始的顶点;
     p[v]: 前驱顶点下标;
     D[v]: 表示从V0到V的最短路径长度和;
     */
    func shortestPath_Dijkstra(_ v: Int) -> (Array<Int>, Array<Int>) {
        // 1 初始化路径数组p = 0;
        var p = Array<Int>(repeating: 0, count: numNodes)
        // 将与V 点有连线的顶点最短路径值;
        var d = arc[v]
        /* final[w] = 1 表示求得顶点V0~Vw的最短路径 */
        var final = Array<Int>(repeating: 0, count: numNodes)
        // V到V的路径为0
        d[v] = 0
        // V到V 是没有路径的.
        final[v] = 1
        // v0到V0是没有路径的
        p[v] = -1
        var k = 0
        // 2. 开始主循环,每次求得V0到某个顶点的最短路径
        for _ in 0 ..< numNodes {
            // 当前所知距离V0顶点最近的距离
            var min = Int.max
            /* 3.寻找离V最近的顶点 */
            for j in 0 ..< numNodes {
                if final[j] == 0 && d[j] < min {
                    k = j
                    min = d[j]
                }
            }
            // 将目前找到最近的顶点置为1;
            final[k] = 1
            /* 4.把刚刚找到v0到v1最短路径的基础上,对于v1 与 其他顶点的边进行计算,得到v0与它们的当前最短距离; */
            for j in 0 ..< numNodes {
                // 如果经过v顶点的路径比现在这条路径长度短,则更新
                if final[j] == 0 && (min < Int.max && arc[k][j] < Int.max && min + arc[k][j] < d[j]) {
                    // 找到更短路径, 则修改D[j],P[j]
                    // 修改当前路径的长度
                    d[j] = min + arc[k][j]
                    p[j] = k
                }
            }
        }
        return (p, d)
    }
}

2、最短路径Floyd算法

#define OK        1
#define ERROR     0
#define TRUE      1
#define FALSE     0
#define MAXEDGE   20
#define MAXVEX    20
#define INFINITYC 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];

/*
 Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。
 Patharc 和 ShortPathTable 都是二维数组;
 */
void ShortestPath_Floyd(MGraph G, Patharc *P, ShortPathTable *D) {
    int v, w, k;

    /* 1. 初始化D与P 矩阵*/
    for (v = 0; v < G.numVertexes; ++v) {
        for (w = 0; w < G.numVertexes; ++w) {
            /* D[v][w]值即为对应点间的权值 */
            (*D)[v][w] = G.arc[v][w];
            /* 初始化P P[v][w] = w*/
            (*P)[v][w] = w;
        }
    }

    //2.K表示经过的中转顶点
    for (k = 0; k < G.numVertexes; ++k) {
        for (v = 0; v < G.numVertexes; ++v) {
            for (w = 0; w < G.numVertexes; ++w) {
                /*如果经过下标为k顶点路径比原两点间路径更短 */
                if ((*D)[v][w] > (*D)[v][k] + (*D)[k][w]) {
                    /* 将当前两点间权值设为更小的一个 */
                    (*D)[v][w] = (*D)[v][k] + (*D)[k][w];
                    /* 路径设置为经过下标为k的顶点 */
                    (*P)[v][w] = (*P)[v][k];
                }
            }
        }
    }
}

swift

struct MGraph {
    var arc: Array<Array<Int>> = Array<Array<Int>>()
    var numNodes: Int = 0, numEdges: Int = 0
    /*
     Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。
     Patharc 和 ShortPathTable 都是二维数组;
     */
    func shortestPath_Floyd() -> (Array<Array<Int>>, Array<Array<Int>>) {
        var p = Array<Array<Int>>()
        var d = Array<Array<Int>>()
        /* 1. 初始化D与P 矩阵*/
        for v in 0 ..< numNodes {
            var pv = Array<Int>()
            var dv = Array<Int>()
            for w in 0 ..< numNodes {
                /* D[v][w]值即为对应点间的权值 */
                dv.append(arc[v][w])
                /* 初始化P P[v][w] = w*/
                pv.append(w)
            }
            p.append(pv)
            d.append(dv)
        }
        // 2.K表示经过的中转顶点
        for k in 0 ..< numNodes {
            for v in 0 ..< numNodes {
                for w in 0 ..< numNodes {
                    /* 如果经过下标为k顶点路径比原两点间路径更短 */
                    if d[v][k] < Int.max && d[k][w] < Int.max && d[v][w] > d[v][k] + d[k][w] {
                        /* 将当前两点间权值设为更小的一个 */
                        d[v][w] = d[v][k] + d[k][w]
                        /* 路径设置为经过下标为k的顶点 */
                        p[v][w] = p[v][k]
                    }
                }
            }
        }
        return (p, d)
    }
}