图的最短路径学习(Dijkstra)

1:Dijkstra算法

  本算法可以算是贪心算法的实现,通过从起点出发去寻找与其他点的最短距离,找到该最短距离的顶点,然后里该顶点为中转点,去寻找

以中转点出发的到其他顶点更近的距离,从而通过一步步的选择找到最优的路径!

2:算法流程

流程如上图所示,v0到其他顶点的距离设置成一个数组path[0,1,5,65535,65535,65535,65535,65535,65535]其中,65535代v0待这个点之间距离无穷大。首先在path中找到最近的一个顶点为v1,然后我们以v1为中转点来更新该数组,怎么更新尼?加入以v0过v1然后达到其他顶点的路径小于v0直接到达其他顶点的路径,则直接用该较小路径来替代数组中数值。依次不断循环来去找到v0到v2,到v3,到v4,到v5,到v6,到v7,到v8的距离。就可以了。

3:代码示例

package nearstWay;

import sun.security.util.Length;

/**
 * @author :dazhu
 * @date :Created in 2020/3/18 11:37
 * @description:最短路径
 * @modified By:
 * @version: $
 */
public class Main {
    public static void main(String[] args){
        //制作顶点数组,邻接矩阵
        int inf = 65535;
        Vertex[] vertexList = new Vertex[]{
                new Vertex("v0"),
                new Vertex("v1"),
                new Vertex("v2"),
                new Vertex("v3"),
                new Vertex("v4"),
                new Vertex("v5"),
                new Vertex("v6"),
                new Vertex("v7"),
                new Vertex("v8")
        };
        int[][] adjMat = new int[][]{
                {  0,  1,  5,inf,inf,inf,inf,inf,inf},
                {  1,  0,  3,  7,  5,inf,inf,inf,inf},
                {  5,  3,  0,inf,  1,  7,inf,inf,inf},
                {inf,  7,inf,  0,  2,inf,  3,inf,inf},
                {inf,  5,  1,  2,  0,  3,  6,  9,inf},
                {inf,inf,  7,inf,  3,  0,inf,  5,inf},
                {inf,inf,inf,  3,  6,inf,  0,  2,  7},
                {inf,inf,inf,inf,  9,  5,  2,  0,  4},
                {inf,inf,inf,inf,inf,inf,  7,  4,  0},
        };
        Graph g = new Graph(vertexList,adjMat);
        Dijkstra djk = new Dijkstra(g);
        djk.findNearestWay(0);
    }
}
class Dijkstra{
    public Graph g = null;
    public int nVertex;
    public int[] pathMatirx;//用于存储最短路径下表的数组
    public int[] shortPathTable;//用于存储个点最短路径的权重值
    public int[] markArr;//markArr[k] = 1代表求得v0到vk的最短路径了
    public Dijkstra(Graph g){
        this.g = g;
        this.nVertex = g.vertexList.length;
        //根据输出的graph顶点数量来初始化数组
        this.pathMatirx =new int[nVertex];
        this.shortPathTable = new int[nVertex];
        this.markArr = new int[nVertex];
    }

    public void findNearestWay(int v0){
        int v=0,w=0,k=0;
        int min;
        //初始化数据
        for(int i=0;i<nVertex;i++){
            this.markArr[i] = 0;
            //初始化shotPathTable为v0到其他顶点的距离
            this.shortPathTable[i] = g.adjMat[v0][i];
            //初始化路径数组为0
            this.pathMatirx[i] = 0;
        }
        //代表v0到v0之间不需要求路径!!
        this.markArr[0] = 1;
        //开始主循环,每次循环求的v0到某个顶点v之间的最短路径,直到所有顶点都求的了!!!
        for(v=1;v<nVertex;v++){
            min = 65535;//当前所知离v0最近的距离,初始化成适当大的值
            //寻找里v0最近的顶点
            for(w =0;w<nVertex;w++) {
                //当且仅当该点没有被寻找最短路径且路径小于min下
                if ((markArr[w]==0)&&shortPathTable[w]<min){
                    //保存最短路径中的顶点于k
                    k = w;
                    //将min替换为该最短路径
                    min = shortPathTable[w];
                }
            }
            //将目前找到的最近顶点置为1,代表着v0到vk已经找到了最短路径
            this.markArr[k] = 1;

            //修正当前最短路径及距离!!
            //如果v0经过前面求得vk到达其他顶点的距离,小于v0直接道道其他顶点的距离
            //则更新v0的shortPathTable[]为最短距离
            for(w =0;w<nVertex;w++){
                if(markArr[w]==0&&min+g.adjMat[k][w]<shortPathTable[w]){
                    shortPathTable[w] = min+g.adjMat[k][w];
                    pathMatirx[w] = k;
                }
            }
        }
    }
}

class Graph{
    public  Vertex[] vertexList;
    public int adjMat[][];
    public int nVerts;

    public Graph(Vertex[] vertexList,int[][] adjMat){
        //初始化,顶点数组
        this.vertexList = vertexList;
        //创建边矩阵
        this.adjMat = adjMat;
        //初始顶点顺序
        this.nVerts = 0;

    }
    //添加顶点到顶点数组
    public void addVertex(String lab){
        vertexList[nVerts++] = new Vertex(lab);
    }

    //添加边到边矩阵
    //weight 0:权值为0的相连
    //weight k:权值为k的相连
    //weight 无穷大:不相连
    public void addEdge(int start,int end,int weight){
        adjMat[start][end] = weight;
        adjMat[end][start] = weight;
    }

    //显示所有顶点
    public void showVertexs(){
        for(int i=0;i<vertexList.length;i++){
            System.out.println(vertexList[i]);
        }
    }
    //打印指定顶点
    public void printVertex(int v){
        System.out.println(vertexList[v].label);
    }

}

//顶点类的结构
//顶点可以存在数组中,用index来表示,
//当然也可以存在链表中
class Vertex{
    public String label;//label
    public boolean wasVisited;//是否遍历过的标记。
    public Vertex(String label){
        this.label = label;
        wasVisited = false;
    }
}

原文地址:https://www.cnblogs.com/dazhu123/p/12519611.html

时间: 2024-10-12 10:00:42

图的最短路径学习(Dijkstra)的相关文章

有向有权图的最短路径算法--Dijkstra算法

Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法, 在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边. 问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径.(单源最短路径) 2.算

带权图的最短路径算法(Dijkstra)实现

一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带权的.不带权的Dijkstra算法要简单得多(可参考我的另一篇:无向图的最短路径算法JAVA实现):而对于带权的Dijkstra算法,最关键的是如何“更新邻接点的权值”.本文采用最小堆主辅助,以重新构造堆的方式实现更新邻接点权值. 对于图而言,存在有向图和无向图.本算法只需要修改一行代码,即可同时实

贪心算法-图的最短路径算法Dijkstra之证明

一.问题:图的最短路径 定义图G=(V,E),而且每条边上的权值非负,求顶点s 到图中任意一点的最短距离.图中任意两点之间的距离定义为:路径上所有边的权值的和. 二.算法:Dijkstra算法 设S是探查的顶点的集合,对每个,我们存储一个距离d(u) 初始S={s},d(s)=0 While S != V 选择一个顶点使得从S到v至少有一条边并且 把v加入到S并且定义 End 三.证明算法的正确性: 只需证明,在算法执行中任意一点的集合S,对每个,路径是最短的s-u路径. 用数学归纳法证明算法的

python数据结构与算法——图的最短路径(Dijkstra算法)

1 # Dijkstra算法——通过边实现松弛 2 # 指定一个点到其他各顶点的路径——单源最短路径 3 4 # 初始化图参数 5 G = {1:{1:0, 2:1, 3:12}, 6 2:{2:0, 3:9, 4:3}, 7 3:{3:0, 5:5}, 8 4:{3:4, 4:0, 5:13, 6:15}, 9 5:{5:0, 6:4}, 10 6:{6:0}} 11 12 13 # 每次找到离源点最近的一个顶点,然后以该顶点为重心进行扩展 14 # 最终的到源点到其余所有点的最短路径 15

模板 图的遍历 bfs+dfs 图的最短路径 Floyed+Dijkstra

广搜 bfs 1 //bfs 2 3 #include<iostream> 4 #include<cstdio> 5 using namespace std; 6 int queue[1001],top=0,end=1; 7 int map[1001][1001]; 8 int vis[1001]; 9 int n,m; 10 void bfs(int p) 11 { 12 queue[end]=p; 13 vis[p]=1; 14 printf("%c -->&q

最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)

一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine-->mine..... 那么,就存在这样一个问题:给定一个单词作为起始单词(相当于图的源点),给定另一个单词作为终点,求从起点单词经过的最少变换(每次变换只会变换一个字符),变成终点单词. 这个问题,其实就是最短路径问题. 由于最短路径问题中,求解源点到终点的最短路径与求解源点到图中所有顶点的最短路径复

最短路径问题-Dijkstra

概述 与前面说的Floyd算法相比,Dijkstra算法只能求得图中特定顶点到其余所有顶点的最短路径长度,即单源最短路径问题. 算法思路 1.初始化,集合K中加入顶点v,顶点v到其自身的最短距离为0,到其它所有顶点为无穷. 2.遍历与集合K中结点直接相邻的边(U,V,C),其中U属于集合K,V不属于集合K,计算由结点v出发,按照已经得到的最短路径到达U,再由U经过该边达到V时的路径长度.比较所有与集合K中结点直接相邻的非集合K结点该路径长度,其中路径长度最小的顶点被确定为下一个最短路径确定的结点

图的单源最短路径:Dijkstra算法实现

本文介绍的是图的非负权值的单源最短路径问题.问题的提出是,对于有权图D,t提供源点v,要找到从v到其他所有点的最短路径,即单源最短路径问题,在本文中,解决这一问题,是普遍比较熟悉的Dijkstra算法. 算法核心思想参见维基.简而言之,设集合S存放已经求出了最短路径的点.初始状态S中只有一个点v0,之后每求得v0到vn的最短路径,就会更新v0到所有vn邻接的点的一致的最短路径(不一定是最终的最短路径),如此重复,每次会确定v0到一个点的最短路径,确定好的点加入S中,直至所有点进入S结束.在本文中

最短路径问题-Dijkstra(基于图的ADT)

基于贪心法的单源最短路径算法 (1)最短路径问题具有最优子结构性质,即最短路径的子路径仍然是最短路径 (2)最短路径问题具有贪心选择性质,为了求的最短路径,Dijkstra提出以最短路径长度递增,逐次生成最短路径的算法   图的ADT以及实现详见:基于相邻矩阵实现图的ADT Dijkstra算法代码: 1 int minVertex(Graphm* g,int *D){ 2 int i,v; 3 for(int i=0;i<g->n();i++){ 4 if(g->getMark(i)=