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

算法-数据结构(图)-迪杰斯特拉最短逻辑算法( Dijkstra)

迪杰斯特拉算法(Dijkstra's Algorithm) 是一种用于计算单源最短路径的经典算法,由荷兰计算机科学家 艾兹赫尔·迪杰斯特拉(Edsger W. Dijkstra) 于1956年提出。它的主要目标是找到从图中的某个源节点到所有其他节点的最短路径。该算法适用于带权有向图无向图,且要求边的权重非负


核心思想

迪杰斯特拉算法采用贪心策略,通过逐步扩展已知的最短路径集合来求解问题。具体步骤如下:

  1. 初始化

    • 设置一个数组 dist[],用于存储从源节点到每个节点的最短距离。初始时,源节点的距离为 0,其他节点的距离为 (表示不可达)。

    • 设置一个数组 visited[],用于标记节点是否已被访问(即是否已找到从源节点到该节点的最短路径)。

    • 设置一个数组 prev[],用于记录每个节点的前驱节点,以便后续重建路径。

  2. 选择当前最短路径节点

    • 从未访问的节点中选择一个距离源节点最近的节点 u(即 dist[u] 最小)。

  3. 更新邻居节点的距离

    • 对于节点 u 的每个邻居节点 v,检查是否存在一条从源节点经过 uv 的路径,且该路径的距离比当前已知的 dist[v] 更短。

    • 如果存在,则更新 dist[v]dist[u] + weight(u, v),并记录 v 的前驱节点为 u

  4. 标记节点为已访问

    • 将节点 u 标记为已访问。

  5. 重复

    • 重复步骤 2~4,直到所有节点都被访问。


算法特点

  1. 适用范围

    • 适用于带权图,且边的权重必须非负

    • 如果图中存在负权边,迪杰斯特拉算法可能会失效,此时可以使用 Bellman-Ford 算法

  2. 时间复杂度

    • 使用**优先队列(堆)**优化后,时间复杂度为 O((V + E) log V),其中 V 是节点数,E 是边数。

    • 如果使用简单的数组实现,时间复杂度为 O(V²)

  3. 空间复杂度

    • 需要额外的空间存储 dist[]visited[]prev[],空间复杂度为 O(V)

算法实现示例

图数据定义



import java.util.ArrayList;
import java.util.List;

//邻接矩阵表示图
public class YuGraph {
    //顶点
    List<Character> vList;
    //边的联通性,初始为0,不联通
    int [][] vG;
    //初始化
    YuGraph(List<Character> list)
    {
        vList=list;
        vG=new int[list.size()][list.size()];
        for(int i=0;i<list.size();i++)
        {
            for(int j=0;j<list.size();j++)
            {
                vG[i][j]=Integer.MAX_VALUE;
            }
        }
    }
    //插入边
    public void insertVg(int i,int j,int val)
    {
        vG[i][j]=val;
    }
}

插入的图

算法实现



import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

//
public class Dijkstra {
    //1.迪杰斯特拉算法
    public static void Dijks(YuGraph yuGraph,int source)
    {
        //顶点数量
        int n=yuGraph.vG.length;
//        System.out.println(n);
        //初始化最短距离
        int [] dist=new int[n];
        //初始设置为无限制大
        Arrays.fill(dist,Integer.MAX_VALUE);
        //目标点设置为0
        dist[source]=0;
        //访问数组标志,默认false
        boolean [] flagArr=new boolean[n];
        //邻接矩阵
        int [][] vG=yuGraph.vG;
        //默认前驱节点
        int[] qianQU=new int [n];
        Arrays.fill(qianQU,-1);
        //遍历所有顶点找距离最小的索引开始更新邻居距离
        for(int i=0;i<n-1;i++)
        {
            //开始访问的点
            int u=findMinIndex(dist,flagArr);
//            System.out.println(u);
            flagArr[u]=true;
            //开始访问它的邻居
            for(int v=0;v<n;v++)
            {
                //没有被访问过,和上一个节点联通,且上一个节点有最短路径,并且新的路径比原来的还要小就更新
                if(!flagArr[v]&&vG[u][v]!=Integer.MAX_VALUE&&dist[u]!=Integer.MAX_VALUE&&dist[u]+vG[u][v]<dist[v])
                {
                    //更新最短距离
                    dist[v]= dist[u]+vG[u][v];
                    //记录前驱
                    qianQU[v]=u;
                }
            }

        }
        printResult(dist,qianQU);

    }
    //2.未访问,最短路径的点的序列
    public static int findMinIndex(int [] dist,boolean [] flagArr)
    {
        int minIndex=-1;
        int minDis=Integer.MAX_VALUE;
        for(int i=0;i<dist.length;i++)
        {

            if(flagArr[i]==false&&dist[i]<minDis)
            {
                minIndex=i;
                minDis=dist[i];
            }
        }
        return minIndex;
    }
    //3.打印最短路径信息
    public static void printResult(int [] dist, int[] qianQU) {
        for (int i = 0; i < dist.length; i++) {
            System.out.print((char) ('A' + i));
            System.out.print(" 最短路径为: ");
            System.out.print(dist[i]);
            System.out.print(" 路径: ");
            printPath(qianQU, i);
            System.out.println();
        }
    }
    // 辅助方法:打印从源节点到目标节点的路径
    public static void printPath(int[] qianQU, int target) {
        if (qianQU[target] != -1) {
            printPath(qianQU, qianQU[target]);
        }
        System.out.print((char) ('A' + target) + " ");
    }

    public static void main(String[] args) {
        List<Character> list=new ArrayList<>();
        for(int i=0;i<5;i++)
        {
            list.add((char)('A'+i));
        }
        YuGraph yuGraph=new YuGraph(list);
        //初始化图
        //ab 10 ac 2
        yuGraph.insertVg(0,1,10);
        yuGraph.insertVg(0,2,2);
        //bd 2
        yuGraph.insertVg(1,3,2);
        //cb5,cd2,ce10
        yuGraph.insertVg(2,1,5);
        yuGraph.insertVg(2,3,2);
        yuGraph.insertVg(2,4,10);
        //de 5
        yuGraph.insertVg(3,4,5);
        //调用迪杰斯特拉最短路径算法
        Dijks(yuGraph,0);
    }
}

相关文章:

  • 使用扩散模型DDPM生成Sine正弦曲线的案例(使用Classifier-free guidance)
  • 力扣——最长递增子序列
  • (二)未来十至二十年的信息技术核心领域(AI、数据库、编程语言)完全零基础者的学习路径与技能提升策略
  • StableDiffusion打包 项目迁移 项目分发 0
  • DeepSeek如何辅助学术写作的性质研究?
  • 什么是回调函数
  • Linux版本控制器Git【Ubuntu系统】
  • RPA 与 AI 结合:开启智能自动化新时代
  • Wireshark Lua 插件教程
  • window基于wsl部署vllm流程及踩坑经历(包含cuda toolkit、nvcc版本问题)
  • 【leetcode hot 100 15】三数之和
  • StableDiffusion本地部署 2
  • TCP的三次握手与四次挥手:建立与终止连接的关键步骤
  • pta天梯L1-003 个位数统计
  • 点云配准技术的演进与前沿探索:从传统算法到深度学习融合(3)
  • Linux上用C++和GCC开发程序实现不同MySQL实例下单个Schema之间的稳定高效的数据迁移
  • Android应用app实现AI电话机器人接打电话
  • 【杂谈】-2025年2月五大大型语言模型(LLMs)
  • 有没有比黑暗森林更黑暗的理论
  • YOLO 检测到人通俗易懂的原理
  • 爱德华多·阿拉纳宣誓就任秘鲁新总理
  • 中国-拉共体论坛第四届部长级会议北京宣言
  • 中华人民共和国和巴西联邦共和国关于强化携手构建更公正世界和更可持续星球的中巴命运共同体,共同维护多边主义的联合声明
  • 哈佛新论文揭示 Transformer 模型与人脑“同步纠结”全过程!AI也会犹豫、反悔?
  • A股高开高走:沪指涨0.82%,创指涨2.63%,超4100股收涨
  • 来伊份:已下架涉事批次蜜枣粽产品,消费者可获额外补偿,取得实物后进一步分析