当前位置: 首页 > backend >正文

数据结构基础内容(第九篇:最短路径)

# 最短路径  

在网络中,求两个不同顶点之间的所有路径 中,边的权值之和最小的那一条路径  

## 无权图的单源最短路算法  

按照递增(非递减)的顺序找出到各个顶 点的最短路  

伪码描述:

```c

void Unweighted ( Vertex S )

{

    Enqueue(S, Q);

    while(!IsEmpty(Q)){

        V = Dequeue(Q);

        for ( V 的每个邻接点 W )

        if(dist[W]==-1 ){

            dist[W] = dist[V]+1;

            path[W] = V;

            Enqueue(W, Q);

        }

    }

}

```

实现  

无权图的单源最短路算法 -  邻接表存储  

dist[] path[]全部初始化为-1

```c

void Unweighted(LGraph Graph, int dist[], int path[], Vertex S){

    Queue Q;

    Vertex V;

    PtrAdjVNode W;

    Q = CreateQueue(Graph->Nv);  // 创建空队列,MaxSize为外部定义的常数

    dist[S] = 0; // 初始化源点

    AddQ(Q, S);

    while (IsEmpty(Q))

    {

        V = DeleteQ(Q);

        for( W = Graph.G[V].FirstEdge; W; W=W->Next)  // 对V的每个邻接点W->AdjV

            if (dist[W->AdjV] == -1)

            {  // W->AdjV 未被访问过

                dist[W->AdjV] =dist[V] + 1;  /* W->AdjV到S的距离更新 */

                path[W->AdjV] = V; /* 将V记录在S到W->AdjV的路径上 */

                AddQ(Q, W->AdjV);

            }

    }

}

```

## 有权图的单源最短路算法

Dijkstra 算法

按照递增的顺序找出到各个顶点的最短路

* 真正的最短路必须只经过S中的顶点  

* 每次从未收录的顶点中选一个dist最小的收录

* 增加一个v进入S,可能影响另外一个w的dist值

    * dist[w] = min{dist[w], dist[v] + <v,w>的权重}

伪码

```c

void Dijkstra( Vertex s )

{

    while (1){

        V = 未收录顶点中dist最小者;

        if ( 这样的V不存在 )

            break;

        collected[V] = true;

        for ( V 的每个邻接点 W ){

            if ( collected[W] == false ){

                if ( dist[V]+E<V,W> < dist[W] ) {

                    dist[W] = dist[V] + E<V,W> ;

                    path[W] = V;

                }

            }

        }

    }

}

```

算法实现

邻接矩阵存储 - 有权图的单源最短路算法

```c

// 返回未被收录顶点中dist最小值

Vertex FindMinDist(MGraph Graph, int dist[], int collected[]){

    Vertex MinV, V;

    int MinDist = INFINITY;

    for(V=0; V<Graph->Nv; V++){

        if (collected[V] = false && dist[V]< MinDist){  /* 若V未被收录,且dist[V]更小 */

            MinDist = dist[V];

            MinV = V;  /* 更新对应顶点 */

        }

    }

    if (MinDist < INFINITY) /* 若找到最小dist */

        return MinV; /* 返回对应的顶点下标 */

    else return ERROR;  /* 若这样的顶点不存在,返回错误标记 */

}


bool Dijkstra(MGraph Graph, int dist[], int path[], Vertex S)

{

    int collected[MaxVertexNum];

    Vertex V, W;

    // 初始化dist[]和path[],邻接矩阵中不存在边的标记为INFINITY

    for(V=0; V<Graph->Nv; V++){

        dist[V] = Graph->G[S][V];

        if (dist[V]<INFINITY)  // S到V有直接路径

            path[V] = S;

        else

            path[V] = -1;

        collected[V] = false;

    }

    // 先将起点收入到集合中

    dist[S] = 0;

    collected[S] = true;

    while(1)

    {

        V = FindMinDist(Graph, dist, collected); /* V = 未被收录顶点中dist最小者 */

        if (V == ERROR)  /* 若这样的V已经不存在 */

            break;

        collected[V] = true;

        for(W=0; W<Graph->Nv; W++){ // 对图中的每个顶点W

            if(collected[W] == false && Graph->G[V][W]<INFINITY)

            {  // 未被收录,且有边(是邻接点)

                if ( Graph->G[V][W]<0 ) /* 若有负边 */

                    return false; /* 不能正确解决,返回错误标记 */

               

                /* 若收录V使得dist[W]变小 */

                if ( dist[V]+Graph->G[V][W] < dist[W] ) {

                    dist[W] = dist[V]+Graph->G[V][W]; /* 更新dist[W] */

                    path[W] = V; /* 更新S到W的路径 */

                }

            }  

        } // for循环结束, 每个V的邻接点W遍历完

    }// while结束

    return true;

}

```

## 多源最短路算法

Floyd 算法  

```c

bool Floyd( MGraph Graph, WeightType D[][MaxVertexNum], Vertex path[][MaxVertexNum] )

{

    Vertex i, j, k;

    /* 初始化 */

    for ( i=0; i<Graph->Nv; i++ )

        for( j=0; j<Graph->Nv; j++ ) {

            D[i][j] = Graph->G[i][j];

            path[i][j] = -1;

        }

    for( k=0; k<Graph->Nv; k++ )

        for( i=0; i<Graph->Nv; i++ )

            for( j=0; j<Graph->Nv; j++ )

                if( D[i][k] + D[k][j] < D[i][j] ) {

                    D[i][j] = D[i][k] + D[k][j];

                    if ( i==j && D[i][j]<0 ) /* 若发现负值圈 */

                        return false; /* 不能正确解决,返回错误标记 */

                    path[i][j] = k;

                }

    return true; /* 算法执行完毕,返回正确标记 */

}

```

http://www.xdnf.cn/news/16381.html

相关文章:

  • DP之背包基础
  • AutoLabelImg:高效的数据自动化标注工具和下载
  • Gradio.NET 中文快速入门与用法说明
  • 2025年7月25日-7月26日 · AI 今日头条
  • 在Luckfox Lyra(Zero W)上将TF卡格式化为ext4文件系统
  • 《 集成异步任务与定时调度:线程池与任务中心设计》
  • AI与区块链Web3技术融合:重塑数字经济的未来格局
  • 2025年项目数据看板工具选型指南,精选12款
  • SQL中的group by和having区别详解
  • 【C语言网络编程】HTTP 客户端请求(基于 Socket 的完整实现)
  • 神经网络知识讨论
  • 网易大模型算法岗面经80道
  • 【学习笔记】MimicGen: 基于人类演示的可扩展机器人学习数据生成系统
  • 批量重命名带编号工具,附免费地址
  • idea打开后project窗口未显示项目名称的解决方案
  • k8s的权限
  • tlias智能学习辅助系统--Filter(过滤器)
  • Ansible列出常见操作系统的发行版,Ansible中使用facts变量的两种方式
  • CH341 Linux驱动 没有 /dev/ttyCH341USB0
  • Linux文件系统管理——NFS服务端的安装配置与NFS客户端的安装与挂载实操教程
  • 【AI】联网模式
  • Scrapy分布式爬虫数据统计全栈方案:构建企业级监控分析系统
  • GPU运维常见问题处理
  • 【C++】stack和queue的模拟实现
  • Java基础day17-LinkedHashMap类,TreeMap类和集合工具类
  • 基于POD和DMD方法的压气机叶片瞬态流场分析与神经网络预测
  • 基于遗传算法的多无人车协同侦察与安全保护策略优化
  • CUDA杂记--FP16与FP32用途
  • Redis面试精讲 Day 5:Redis内存管理与过期策略
  • 汇编语言中的通用寄存器及其在逆向工程中的应用