十大常用算法之地杰斯特拉算法

十大常用算法的完整实现

一、二分查找算法:https://blog.csdn.net/weixin_46635575/article/details/121532149
二、分治算法:https://blog.csdn.net/weixin_46635575/article/details/121532941
三、动态规划算法:https://blog.csdn.net/weixin_46635575/article/details/121534074
四、KMP算法:https://blog.csdn.net/weixin_46635575/article/details/121590510
五、贪心算法:https://blog.csdn.net/weixin_46635575/article/details/121626626
六、普利姆算法:https://blog.csdn.net/weixin_46635575/article/details/121653256
七、克鲁斯卡尔算法:https://blog.csdn.net/weixin_46635575/article/details/121670374
八、地杰斯特拉算法:https://blog.csdn.net/weixin_46635575/article/details/121692675
九、佛洛依德算法:https://blog.csdn.net/weixin_46635575/article/details/121714678
十、马踏棋盘算法(周游骑士算法):https://blog.csdn.net/weixin_46635575/article/details/121716596

1、基本介绍

(1)应用场景

在这里插入图片描述

(2)介绍

在这里插入图片描述
回忆一下我们的图的广度优先和深度优先
在这里插入图片描述

  • 广度优先是从一层一层的访问:所以是12345678
  • 深度优先是先走到底,然后回到起点进行重新查找,如果还是不是很理解的话,建议你去看一下我主页的图的算法的文章。

在这里插入图片描述

  • v就是我们例子中的G点,Dis里面记录的是v到图中各个节点的距离

(3)图解我们的题目

在这里插入图片描述

  • 当以G开始走一遍后
    在这里插入图片描述
    在这里插入图片描述
    当G访问后,接下来开始访问A开始访问。这时候三个数组也是要进行更新的,这时候的出发顶点任然是G点,只是以A点访问而已,不然我们无法记录G到各个顶点的距离。

  • 需要创建的数组
    在这里插入图片描述

2、代码编写

来看我们分析写代码的顺序
在这里插入图片描述
在这里插入图片描述

  • 首先我要去编写初始化图的一个类,并且初始化图
  • 第二步我是要完成目的1
  • 第三步我们要完成目的2

(1)先初始化我们的图

  • 这个到后面也是很重要的,所以请把这里看懂了,挺简单的
package cn.mldn.dijkstra;

import java.util.Arrays;

public class DijkstraAlgorithm {
    public static void main(String[] args) {
        //先初始化我们的图
        char[] vertex = {'A','B','C','D','E','F','G'};
        //领接矩阵
        int[][] matrix = new int[vertex.length][vertex.length];
        final  int N = 65535;//表示不可连接
        matrix[0] =new int[]{N,5,7,N,N,N,2};
        matrix[1] =new int[]{5,N,N,9,N,N,3};
        matrix[2] =new int[]{7,N,N,N,8,N,N};
        matrix[3] =new int[]{N,9,N,N,N,4,2};
        matrix[4] =new int[]{N,N,8,N,N,5,4};
        matrix[5] =new int[]{N,N,N,4,5,N,6};
        matrix[6] =new int[]{2,3,N,N,4,6,N};

        //这是一部分的测试
        Graph graph = new Graph(vertex, matrix);
        graph.showGraph();
    }
}


class Graph {
    private char[] vertex;//存放顶点数组
    private int[][] matrix;//领接矩阵

    public Graph(char[] vertex,int[][] matrix) {
        this.vertex = vertex;
        this.matrix = matrix;
    }

    //显示图
    public void showGraph() {
        for (int[] link: matrix) {
            System.out.println(Arrays.toString(link));
        }
    }
}

(2)完成目的1

  • 首先要去看VisitedVertex 类的所有方法
  • 然后再去看我们增加在Graph图里面的方法
import java.util.Arrays;

public class DijkstraAlgorithm {
    public static void main(String[] args) {
        //先初始化我们的图
        char[] vertex = {'A','B','C','D','E','F','G'};
        //领接矩阵
        int[][] matrix = new int[vertex.length][vertex.length];
        final  int N = 65535;//表示不可连接
        matrix[0] =new int[]{N,5,7,N,N,N,2};
        matrix[1] =new int[]{5,N,N,9,N,N,3};
        matrix[2] =new int[]{7,N,N,N,8,N,N};
        matrix[3] =new int[]{N,9,N,N,N,4,2};
        matrix[4] =new int[]{N,N,8,N,N,5,4};
        matrix[5] =new int[]{N,N,N,4,5,N,6};
        matrix[6] =new int[]{2,3,N,N,4,6,N};

        //这是一部分的测试
        Graph graph = new Graph(vertex, matrix);
        graph.showGraph();


        //第二部分的测试
        graph.dsj(6);
    }
}

//表示已经访问过的集合
class VisitedVertex {
    //记录各个顶点是否访问过1表示已经访问过,0表没有访问
    public int[] already_arr;

    //每个下标对应的值为前一个顶点的下标,会动态更新
    public int[] pre_visited;

    //记录出发点到其他所有节点的距离,比如G为出发点,就会记录到其他顶点的距离,会动态更新,求的最短距离就会放到dis里面
    public int[] dis;

    //构造器

    /**
     *
     * @param length 你要给我长度
     * @param index 你是从那个顶点开始处理的:即出发顶点
     */
    public VisitedVertex(int length,int index) {
        this.already_arr = new int[length];
        this.pre_visited = new int[length];
        this.dis = new int[length];
        //初始化dis数组,除了自己那个点为0
        Arrays.fill(dis,65535);
        this.already_arr[index] = 1;//设置出发顶点被访问过
        this.dis[index] = 0;
    }

    /**
     * 判断index顶点是否被访问过
     * @param index
     * @return 被访问过就是true
     */
    public boolean in(int index) {
        return already_arr[index] == 1;
    }

    /**
     * 更新出发节点到index顶点的距离【对应dis数组】
     * @param index
     * @param len
     */
    public void updateDis(int index,int len) {
        dis[index] = len;
    }

    /**
     * 更新pre顶点的前驱为index的节点【对应我们的pre_visited】
     * @param pre
     * @param index
     */
    public void updatePre(int pre,int index) {
        pre_visited[pre] = index;
    }

    /**
     * 返回出发顶点到index的距离【对应我们的dis数组】
     * @param index
     */
    public int getDis(int index) {
        return dis[index];
    }


}



class Graph {
    private char[] vertex;//存放顶点数组
    private int[][] matrix;//领接矩阵

    public Graph(char[] vertex,int[][] matrix) {
        this.vertex = vertex;
        this.matrix = matrix;
    }

    //显示图
    public void showGraph() {
        for (int[] link: matrix) {
            System.out.println(Arrays.toString(link));
        }
    }

    private VisitedVertex vv;//表示已经访问的顶点的集合


    /**
     * 地杰斯特拉算法
     * @param index 表示出发顶点的下标
     */
    public void dsj(int index) {
        vv = new VisitedVertex(vertex.length,index);
        update(index);//更新index顶点到周围顶点的距离和前驱顶点
    }

    //更新index下标顶点到周围顶点的距离和周围顶点的前驱顶点
    private void update(int index) {
        int len = 0;
        //根据遍历我们的领接矩阵,即matrix[index]这一行
        for (int i = 0; i < matrix[index].length; i++) {
            //这时候的len表示,出发点到index顶点的距离 + 从index顶点到j顶点的距离
            len = vv.getDis(index) + matrix[index][i];
            //如果i这个节点没有被访问过,并且len小于出发节点到j顶点的距离,就需要更新
            if (!vv.in(i) && len < vv.getDis(i)) {
                vv.updatePre(i,index);//更新i这个节点的前驱节点为index顶点
                vv.updateDis(i,len);//更新出发顶点到i顶点的距离
            }
        }
    }
}

(3)完成目的2

完成上面,就相当于完成了过程图中的目的1,接下来完成目的2

  • 首先在我们的VisitedVertex追加如下方法
/**
     * 继续选择并返回新的访问顶点,比如这里的G完后,就要A作为新的访问顶点【不是以这个为出发点】
     * @return
     */
    public int updateArr() {
        int min = 65535;
        int index = 0;
        for (int i = 0; i < already_arr.length; i++) {
            if (already_arr[i] == 0 && dis[i] < min) {
                min = dis[i];
                index = i;
            }
        }
        //同时更新index顶点被访问过
        already_arr[index] = 1;
        return index;
    }

    
    //用于后面的显示
    public void show() {
        System.out.println("============================");
        for (int i: already_arr) {
            System.out.print(i + " ");
        }

        System.out.println();
        System.out.println("****************************");
        for (int i: pre_visited) {
            System.out.print(i + " ");
        }

        System.out.println();
        System.out.println("----------------------------");
        for (int i: dis) {
            System.out.print(i + " ");
        }
    }
  • 然后修改我们的的MGraph里面的djs方法和追加我们的show方法
/**
     * 地杰斯特拉算法
     * @param index 表示出发顶点的下标
     */
    public void dsj(int index) {
        vv = new VisitedVertex(vertex.length,index);
        update(index);//更新index顶点到周围顶点的距离和前驱顶点

        for (int i = 0; i < vertex.length; i++) {
            index = vv.updateArr();//选择并返回新的访问顶点
            update(index);//更新index顶点到周围顶点的距离和前驱顶点
        }
    }
    
    
    //用于后续的显示
    public void djsShow() {
        vv.show();
    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值