最短路径问题(Dijkstra算法、Floyd算法)

本文主要讨论带权有向图的两个问题:

  • 求某一顶点到其它顶点的最短路径;
  • 求任意一对顶点之间的最短路径。

目录

一、Dijkstra算法

1.1 基本思想

1.2 算法思想

1.3 算法实现

二、Floyd算法

2.1 基本思想

2.2 算法实现

三、辅助函数


一、Dijkstra算法

1.1 基本思想

迪杰斯特拉(Dijkstra)提出了求解这种问题的方法。

1.2 算法思想

辅助数组dist[ ]:dist[i]表示目前已经找到的从开始点到终点的当前最短路径长度。

辅助数组path[ ]:path[i]表示目前已经找到的从开始点到终点的当前最短路径顶点序列。

 

1.3 算法实现

#define INFINITY 32768
typedef int WeightType;
typedef SeqList VertexSet; /* 线性表 —— 顶点集 */

Member函数用于判断顶点是否在顶点集S中。

bool Member(VertexData v, VertexSet *S) {
    for (int i = 0; i < S->last; ++i)
        if (v == S->elem[i])
            return true;

    return false;
}

Dijkstra算法。

void ShortestPath_DJS(Graph *G, int v0, WeightType dist[], VertexSet path[]) {
    /* 初始化辅助数组dist和path */
    for (int i = 0; i < G->vexnum; ++i) {
        InitList(&path[i]);
        dist[i] = G->arcs[v0][i].adjvex;
        if (dist[i] < INFINITY) {
            /* AddTail是表尾添加操作 */
            AddTail(&path[i], G->vertex[v0].data);
            AddTail(&path[i], G->vertex[i].data);
        }
    }

    VertexSet S; /* S为已找到最短路径的终点集合 */
    InitList(&S);
    AddTail(&S, G->vertex[v0].data);

    int k, min;
    for (int t = 1; t <= G->vexnum - 1; ++t) {
        min = INFINITY;
        for (k = -1, i = 0; i < G->vexnum; ++i)
            if (!Member(G->vertex[i].data, & S) && dist[i] < min) {
                k = i;
                min = dist[i];
            }
        /* 未找到合适的终点,直接进入下一趟循环 */
        if (k == -1) continue;
        
        /* 将Vk加入到S中 */
        AddTail(&S, G->vertex[k].data);

        /* 修正dist[i] */
        for (int i = 0; i < G->vexnum; ++i) 
            if (!Member(G->vertex[i].data, &S) && G->arcs[k][i].adjvex 
            != INFINITY && (dist[k] + G->arcs[k][i].adjvex < dist[i])) {
                dist[i] = dist[k] + G->arcs[k][i].adjvex;
                path[i] = path[k];
                /* path[i] = path[k]∪{Vi} */
                AddTail(&path[i], G->vertex[i].data);
            }
    }
}


二、Floyd算法

2.1 基本思想

下面给出一个例子。

 

第一次迭代,加入顶点a:

第二次迭代,加入顶点b:

第三次迭代,加入顶点c:

 

2.2 算法实现

void ShortestPath_Floyd(AdjMatrix *G,
                        WeightType dist[][MAX_VERTEX_NUM],
                        VertexSet path[][MAX_VERTEX_NUM]) {
    int i, j, k;

    /* 初始化辅助数组dist和path */
    for (i = 0; i < G->vexnum; ++i)
        for (j = 0; j < G->vexnum; ++j) {
            InitList(&path[i][j]);
            dist[i][j] = G->arcs[i][j].adjvex;
            if (dist[i][j] < INFINITY) {
                AddTail(&path[i][j], G->vertex[i].data);
                AddTail(&path[i][j], G->vertex[j].data);
            }
        }

    /* 进行n次迭代,找出最短路径 */
    for (k = 0; k < G->vexnum; k++)
        for (i = 0; i < G->vexnum; i++)
            for (j = 0; j < G->vexnum; j++)
                if (dist[i][k] + dist[k][j] < dist[i][j]) {
                    dist[i][j] = dist[i][k] + dist[k][j];
                    /* JoinList是合并线性表操作 */
                    JoinList(&path[i][k], &path[k][j], &path[i][j]);
                }
}

 


三、辅助函数

算法中使用到的辅助函数:

  • AddTail
  • JoinList
  • ListLength
  • InitList
bool AddTail(LListPtr L, ElemType e) {
    return InsList(L, L->last + 1, e);
}

void JoinList(LListPtr La, LListPtr Lb, LListPtr Lc) {
    int i, j;

    for (i = 0; i < La->last; ++i)
        Lc->elem[i] = La->elem[i];
    for (--i, j = 0; j < Lb->last; ++i, ++j)
        Lc->elem[i] = Lb->elem[j];
    Lc->last = i;
}

int ListLength(LListPtr L) {
    return L->last;
}

void InitList(LListPtr L) {
    L->last = 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值