最短路径:迪杰斯特拉算法

这篇具有很好参考价值的文章主要介绍了最短路径:迪杰斯特拉算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

        英文名Dijkstra

        作用:找到路中指定起点到指定终点的带权最短路径

核心步骤

        1)确定起点,终点

        2)从未走过的点中选取从起点到权值最小点作为中心点

        3)如果满足 起点到中心点权值 + 中心点到指定其他点的权值 < 起点到其他点的权值,

        即Weight[start] [center] +Weight [center] [other] < Weight [start] [center] ,

        简言之,有更短的路径就取更短的路

理论模拟

        以A为起点,D为终点,如图所示 径, 更新记录更短权值路径

最短路径:迪杰斯特拉算法,数据结构与算法,算法,数据结构

 从未走过的点中选取权值最小点,即A作为中心点,标记A走过,更新起点到B、F、G的路径

 最短路径:迪杰斯特拉算法,数据结构与算法,算法,数据结构

从未走过的点中选取权值最小点,即B, 并且W:B->C + W:A->C = 12 + 10 < +oo ,更新起点A到C的路径和,

即W: A-> C =W: A-> B -> C =12+10 =22

 最短路径:迪杰斯特拉算法,数据结构与算法,算法,数据结构

 继续从未走过的点中选取权值最小点G, W: A -> E =+oo > W: A->G ->E =14+8 =22 ,

 更新W: A->E 为22

最短路径:迪杰斯特拉算法,数据结构与算法,算法,数据结构

选取F, 由于W:A->F->E=16+2 =18 <22 更新 W: A-> E =18 ,

最短路径:迪杰斯特拉算法,数据结构与算法,算法,数据结构

 选取E,由于W:A->E->D=18+4=22<+oo,则更新W: A->D =22

最短路径:迪杰斯特拉算法,数据结构与算法,算法,数据结构

 选取C,无可更新点

最短路径:迪杰斯特拉算法,数据结构与算法,算法,数据结构

 到达终点D! 最短路径为A->F->E->D ,最短路径和为22

最短路径:迪杰斯特拉算法,数据结构与算法,算法,数据结构

 文章来源地址https://www.toymoban.com/news/detail-713208.html

Java代码实现
 顶点
//顶点类
public class Vertex {
    public String Number;  //顶点编号
    public List<Vertex>neighborVertexs;    //邻居顶点
    public Map<Vertex,Integer>weights;     //与邻居节点之间的权值

    public Vertex(String number) {
        this.Number = number;
        this.neighborVertexs=new LinkedList<>();
        this.weights=new HashMap<>();
    }
}
public class Edge {
    public Vertex start;
    public Vertex end;
    public Integer weight;

    public Edge(Vertex start, Vertex end, Integer weight) {
        this.start = start;
        this.end = end;
        this.weight = weight;
    }
}
最短路径返回结果
public class MinPathResult {
    public String minPathString;    //将最短路径拼接成字符串形式,如 A->B->C
    public List<Vertex>minPathList; //将起点到终点的路径储存在List集合中
    public Integer minPathSum;  //记录起点到终点的最短路径和
    public MinPathResult(List<Vertex> minPathList, String minPathString,Integer minPathSum) {
        this.minPathString = minPathString;
        this.minPathList = minPathList;
        this.minPathSum=minPathSum;
    }

    @Override
    public String toString() {
        return "Result{" +
                "minPathString:'" + minPathString +"  minPathSum:"+minPathSum+
                '}';
    }
}
Dijkstra算法的实现,适用于无向图
import java.util.*;
//适用于无向图
public class DijkstraOperator {
    private List<Vertex>vertexs;    //全部顶点
    private List<Edge>edges;        //所有边
    private Map<String,Vertex>vertexs_map;  //通过顶点编号找到顶点

    private final static Integer INF=Integer.MAX_VALUE;     //代表无穷大

    public DijkstraOperator(List<Vertex> vertexs, List<Edge> edges) {
        this.vertexs = vertexs;
        this.edges = edges;
        this.vertexs_map=new HashMap<>();
        //构建编号映射顶点
        for(Vertex v:vertexs)
        {
            vertexs_map.put(v.Number,v);
        }

        //填充所有顶点的邻居以及权值
        for(int i=0;i<edges.size();i++)
        {
            //填充起点的邻居,以及起点到终点的权值
            edges.get(i).start.neighborVertexs.add(edges.get(i).end);
            edges.get(i).start.weights.put(edges.get(i).end,edges.get(i).weight);

            //填充终点的邻居,以及终点到起点的权值
            edges.get(i).end.neighborVertexs.add(edges.get(i).start);
            edges.get(i).end.weights.put(edges.get(i).start,edges.get(i).weight);
        }
    }
    //获得从起点到终点之间的路径
    public MinPathResult getMinPath(String start, String end){
        //用哈希表标记某个顶点是否走过
        Map<Vertex,Boolean>visited=new HashMap<>();
        //用哈希表记录顶点的前驱
        Map<Vertex,Vertex>preVertex=new HashMap<>();
        //利用哈希表记录起点到任意一点的最短路径
        Map<Vertex,Integer>minPath=new HashMap<>();

        //初始化三个表
        for(int i=0;i<vertexs.size();i++)
        {
            //初始化每一个点都未走过
            visited.put(vertexs.get(i),false);
            //初始化每个点的前驱都是自己
            preVertex.put(vertexs.get(i),vertexs.get(i));
            //初始化起点到任意两个点之间的最短路径都是无穷大
            minPath.put(vertexs.get(i),INF);
        }

        Vertex startVertex=vertexs_map.get(start);
        Vertex endVertex=vertexs_map.get(end);

        //填充存在的路径
        for(int i=0;i<startVertex.neighborVertexs.size();i++)
        {
            //设置起点与邻居节点之间的权值
            minPath.put(startVertex.neighborVertexs.get(i),startVertex.weights.get(startVertex.neighborVertexs.get(i)));
            //设置点前驱
            preVertex.put(startVertex.neighborVertexs.get(i),startVertex);
        }
        //自己到自己的距离为0
        minPath.put(startVertex,0);

        Vertex curVertex=null;
        //一直寻路,直到找到终点
        while(curVertex!=endVertex)
        {
            Integer minWeight=Integer.MAX_VALUE;
            curVertex=null;
            //能看到的点之间选取距离最小的那个,且这个点并没有走过
            for(Vertex v:minPath.keySet())
            {
                if(!visited.get(v)&&minPath.get(v)<minWeight)
                {
                    //切换中心点
                    curVertex=v;
                    //更新最小权值
                    minWeight=minPath.get(v);
                }
            }

            //如果找不到下一个中心点,说明从起点根本到达不来终点
            if(curVertex==null)
                return null;
            //标记选取点
            visited.put(curVertex,true);

            //更新权值
            for(int i=0;i<curVertex.neighborVertexs.size();i++)
            {
                //邻居节点
                Vertex neighborVertex=curVertex.neighborVertexs.get(i);

                //计算起点到邻居节点之间新的权值
                int newWeight=minPath.get(curVertex)+curVertex.weights.get(neighborVertex);

                //找到能移动的点,如果转折之后距离更短,则记录更短的距离
                if(visited.get(neighborVertex)==false&&newWeight<minPath.get(neighborVertex))
                {
                    //记录更短距离
                    minPath.put(neighborVertex,newWeight);

                    //记录邻居节点的前驱
                    preVertex.put(neighborVertex,curVertex);
                }
            }
        }
        //起点到终点之间的最短路径
        LinkedList<Vertex>targetPath=new LinkedList<>();

        for(Vertex curVer=endVertex;curVer!=startVertex;curVer=preVertex.get(curVer))
        {
            targetPath.addFirst(curVer);
        }
        targetPath.addFirst(startVertex);

        //拼接最短路径
        StringBuffer minPathStringBuffer=new StringBuffer();
        Integer pathSum=0;
        for(int i=0;i< targetPath.size();i++)
        {
            minPathStringBuffer.append(targetPath.get(i).Number);
            if(i!= targetPath.size()-1)
            {
                pathSum=pathSum+targetPath.get(i).weights.get(targetPath.get(i+1));
                minPathStringBuffer.append("->");
            }
        }
        return new MinPathResult(targetPath, minPathStringBuffer.toString(),pathSum);
    }
}
测试函数
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);

        List<Vertex>vertexs=new LinkedList<>();
        List<Edge>edges=new LinkedList<>();

        System.out.println("请输入顶点的数量:");
        Integer vexcnt= scanner.nextInt();
        System.out.println("请输入这些顶点编号:");
        for(int i=0;i<vexcnt;i++)
        {
            vertexs.add(new Vertex(scanner.next()));
        }

        System.out.println("请输入边的数量:");
        Integer edgecnt= scanner.nextInt();
        System.out.println("请输入这些边的端点编号和权值:");
        for(int i=0;i<edgecnt;i++)
        {
            String number1= scanner.next();
            String number2= scanner.next();
            Integer weight= scanner.nextInt();

            Vertex v1=null;
            Vertex v2=null;
            for(int j=0;j<vertexs.size();j++)
            {
                if(vertexs.get(j).Number.equals(number1))
                    v1=vertexs.get(j);
                if(vertexs.get(j).Number.equals(number2))
                    v2=vertexs.get(j);
            }
            edges.add(new Edge(v1,v2,weight));
        }

        //定义迪杰斯特拉操作类
        DijkstraOperator dijkstra=new DijkstraOperator(vertexs,edges);

        //获取任意两点之间的最短路径结果集
        List<MinPathResult>minPathResults=new ArrayList<>();

        for(int i=0;i< vertexs.size();i++)
        {
            for(int j=i+1;j< vertexs.size();j++)
            {
                minPathResults.add(dijkstra.getMinPath(vertexs.get(i).Number,vertexs.get(j).Number));
                System.out.println(minPathResults.get(minPathResults.size()-1));
            }
        }

    }
}
测试输入与输出结果
//输入部分
请输入顶点的数量:
7
请输入这些顶点编号:
A B C D E F G
请输入边的数量:
12
请输入这些边的端点编号和权值:
A B 12
A F 16
A G 14
B C 10
B F 7
G F 9
G E 8
F C 6
F E 2
C D 3
C E 5
E D 4

//输出部分
Result{minPathString:'A->B  minPathSum:12}
Result{minPathString:'A->B->C  minPathSum:22}
Result{minPathString:'A->F->E->D  minPathSum:22}
Result{minPathString:'A->F->E  minPathSum:18}
Result{minPathString:'A->F  minPathSum:16}
Result{minPathString:'A->G  minPathSum:14}
Result{minPathString:'B->C  minPathSum:10}
Result{minPathString:'B->F->E->D  minPathSum:13}
Result{minPathString:'B->F->E  minPathSum:9}
Result{minPathString:'B->F  minPathSum:7}
Result{minPathString:'B->F->G  minPathSum:16}
Result{minPathString:'C->D  minPathSum:3}
Result{minPathString:'C->E  minPathSum:5}
Result{minPathString:'C->F  minPathSum:6}
Result{minPathString:'C->E->G  minPathSum:13}
Result{minPathString:'D->E  minPathSum:4}
Result{minPathString:'D->E->F  minPathSum:6}
Result{minPathString:'D->E->G  minPathSum:12}
Result{minPathString:'E->F  minPathSum:2}
Result{minPathString:'E->G  minPathSum:8}
Result{minPathString:'F->G  minPathSum:9}

进程已结束,退出代码为 0

到了这里,关于最短路径:迪杰斯特拉算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构学习记录——图-最短路径问题(无权图单源最短路径算法、有权图单源最短路径算法、多源最短路径算法、Dijkstra(迪杰斯特拉)算法、Floyd算法)

    目录 问题分类  无权图单源最短路径算法 思路 伪代码 时间复杂度 代码实现(C语言) 有权图单源最短路径算法 Dijkstra(迪杰斯特拉)算法 伪代码  时间复杂度  代码实现(C语言) 多源最短路径算法 两种方法 Floyd算法 代码实现(C语言) 最短路径问题的抽象 在网络中,求

    2024年02月08日
    浏览(49)
  • 数据结构第13周 :( 迪杰斯特拉最短路径 + 弗洛伊德求最短路径 + 欧拉回路 + Invitation Cards)

    【问题描述】 在带权有向图G中,给定一个源点v,求从v到G中的其余各顶点的最短路径问题,叫做单源点的最短路径问题。 在常用的单源点最短路径算法中,迪杰斯特拉算法是最为常用的一种,是一种按照路径长度递增的次序产生最短路径的算法。 在本题中,读入一个有向图

    2024年02月13日
    浏览(25)
  • 【数据结构与算法】迪杰斯特拉算法

    介绍 迪杰斯特拉(Dijkstra)算法是 典型最短路径算法 ,用于计算一个节点到其他节点的最短路径。它的主要特点是以中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。 算法过程 设置出发顶点为 v,顶点集合 V{v1,v2,v3…vi},v 到 V 中各顶点的距离构成距离集合

    2024年02月11日
    浏览(35)
  • 数据结构--迪杰斯特拉(Dijkstra)算法

    生活封锁了我们,只要我们的心不死,生活便永远不是一汪死水,而我们,依然会绽放最美的姿态。 戴克斯特拉算法(英语:Dijkstra’s algorithm),又称迪杰斯特拉算法、Dijkstra算法,是由荷兰计算机科学家艾兹赫尔·戴克斯特拉在1956年发现的算法,并于3年后在期刊上发表。

    2024年02月04日
    浏览(38)
  • 大话数据结构-迪杰斯特拉算法(Dijkstra)和弗洛伊德算法(Floyd)

      最短路径,对于图来说,是两顶点之间经过的边数最少的路径;对于网来说,是指两顶点之间经过的边上权值之和最小的路径。路径上第一个顶点为源点,最后一个顶点是终点。   以如下无向图为例:   我们来计算下标为0的顶点,到其他顶点的最短路径,首先定义

    2024年02月06日
    浏览(32)
  • 最短路径:迪杰斯特拉算法

    简介         英文名Dijkstra         作用:找到路中指定起点到指定终点的带权最短路径 核心步骤         1)确定起点,终点         2)从未走过的点中选取从起点到权值最小点作为中心点         3)如果满足 起点到中心点权值 + 中心点到指定其他点的

    2024年02月08日
    浏览(30)
  • 最短路径——迪杰斯特拉算法

    日常生活中常常涉及最短路径问题,如在一个城市交通网中,如何选取从起点到达终点的路径,才能使这一趟旅程的路程最短?或所需时间最少?或所需交通费用最低?诸如此类问题都可以抽象为 求解图的最短路径问题 。我们把 图的顶点 表示为 城市的交通站点 , 边表示交

    2024年02月04日
    浏览(37)
  • 【数据结构】最短路径算法实现(Dijkstra(迪克斯特拉),FloydWarshall(弗洛伊德) )

    最短路径问题 :从在带权有向图G中的某一顶点出发,找出一条通往另一顶点的最短路径,最短也就是沿路径各边的权值总和达到最小。 单源最短路径问题:给定一个图G = ( V , E ) G=(V,E)G=(V,E),求源结点s ∈ V s∈Vs∈V到图 中每个结点v ∈ V v∈Vv∈V的最短路径 针对一个带权

    2024年02月04日
    浏览(40)
  • 迪杰斯特拉算法(求最短路径)

    迪杰斯特拉算法用于查找图中某个顶点到其它所有顶点的最短路径,该算法既适用于无向加权图,也适用于有向加权图。 注意,使用迪杰斯特拉算法查找最短路径时,必须保证图中所有边的权值为非负数,否则查找过程很容易出错。 迪杰斯特拉算法的实现思路 图 1 是一个无

    2024年02月02日
    浏览(29)
  • 迪杰斯特拉算法 – 图的单源最短路径

    迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。迪杰斯特拉算法采

    2024年02月05日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包