Dijkstra算法(附可执行完整Java代码)(二)

原理(一定要理解参透)请参照上篇博客:

https://blog.csdn.net/qq_42789954/article/details/112531417

此篇文章只是在上篇文章代码上进行了些许优化,可读性以及演示效果更好。

图依然是上篇的图:

在这里插入图片描述

不多说,直接上代码。

1. 代码

import java.util.ArrayList;
import java.util.Scanner;

public class Dijkstra_MoreFun {
    private final int num_of_nodes = 9;  //定义图中节点个数
    private int start;
    private int end;
    private int initial_start;
    private int biggest;
    private ArrayList<Integer> point_list;
    private boolean[] visited;
    private int[] cal_distance;
    private int[] distance;
    private int[] parent;
    private int[][] graph;

    public static void main(String[] args) {
        Dijkstra_MoreFun dijkstra = new Dijkstra_MoreFun();
        dijkstra.test();
    }

    private void test() {
        //调用初始化方法进行初始化
        initializer_parameter();
        initializer_adjacent_matrix();
        //对节点编号范围进行提示
        System.out.println("节点编号范围为:" + 0 + "~" + (num_of_nodes - 1));
        //调用设置起点与终点方法
        set_start_point();
        set_end_point();
        distance[start] = 0;

        while (point_list.size() != 1) {
            if (end == start) {
                System.out.println("起点与终点重合");
                break;
            }
            update();
            visited_remove(start);
            int min_distance = find_min();
            if (!estimate(min_distance)) {
                break;
            }
        }
        show_path();
    }

    //参数初始化程序
    private void initializer_parameter() {
        biggest = Integer.MAX_VALUE;
        point_list = new ArrayList<>();
        for (int i = 0; i < num_of_nodes; i++) {
            //point_list.add(i);不能直接这样使用,必须要先在上面创建对象!!!
            point_list.add(i);
        }
        visited = new boolean[]{false, false, false, false, false, false, false, false, false};
        cal_distance = new int[9];
        distance = new int[]{biggest, biggest, biggest, biggest, biggest, biggest, biggest, biggest, biggest};
        parent = new int[]{-1, -1, -1, -1, -1, -1, -1, -1, -1};
    }

    //邻接矩阵初始化程序
    private void initializer_adjacent_matrix() {
        graph = new int[][]{
                {0, 4, biggest, biggest, biggest, biggest, biggest, 8, biggest},
                {4, 0, 8, biggest, biggest, biggest, biggest, 3, biggest},
                {biggest, 8, 0, 7, biggest, 4, biggest, biggest, 2},
                {biggest, biggest, 7, 0, 9, 14, biggest, biggest, biggest},
                {biggest, biggest, biggest, 9, 0, 10, biggest, biggest, biggest},
                {biggest, biggest, 4, 14, 10, 0, 2, biggest, biggest},
                {biggest, biggest, biggest, biggest, biggest, 2, 0, 6, 6},
                {8, 3, biggest, biggest, biggest, biggest, 6, 0, 1},
                {biggest, biggest, 2, biggest, biggest, biggest, 6, 1, 0}
        };
    }

    //设置起点编号,并校验合法性
    private void set_start_point() {
        System.out.println("请输入起点编号:");
        Scanner sc = new Scanner(System.in);
        start = sc.nextInt();
        while (start < 0 || start > num_of_nodes - 1) {
            System.out.println("输入的起点编号超出范围,请重新输入:");
            start = sc.nextInt();
        }
        initial_start = start;
    }

    //设置终点编号,并校验合法性
    private void set_end_point() {
        System.out.println("请输入终点编号:");
        Scanner sc = new Scanner(System.in);
        end = sc.nextInt();
        while (end < 0 || end > num_of_nodes - 1) {
            System.out.println("输入的终点编号超出范围,请重新输入:");
            end = sc.nextInt();
        }
    }

    //更新 distance 和 parent 数组
    private void update() {
        for (Integer node : point_list) {
            if (graph[start][node] != biggest) {
                cal_distance[node] = graph[start][node] + distance[start];
                if (cal_distance[node] < distance[node]) {
                    distance[node] = cal_distance[node];
                    parent[node] = start;
                }
            }
        }
    }

    //从点集合中删除被搜索过的点
    private void visited_remove(int searched) {
        visited[start] = true;
        point_list.remove(Integer.valueOf(searched));
    }

    //遍历 删除已经搜索过的点 的点集合,得到对应的编号
    //再根据编号搜索 distance 集合中的最小值,得到最小值对应的节点编号,作为下一个等待搜索的点
    private int find_min() {
        int min = biggest;
        for (Integer node : point_list) {
            if (distance[node] < min) {
                min = distance[node];
                start = node;
            }
        }
        return min;
    }

    //判断 min 与 start 的值
    private boolean estimate(int min) {
        if (min != biggest && start == end) {
            //这种情况说明已经找到了到终点的路径,且这条路径还最短,可以结束搜索了
            System.out.println("已经找到了最短路径,路径长度为:" + min + "。后续不再进行搜索");
            return false;
        } else if (min == biggest) {
            //起点到其他节点间全为不可达,不论是到终点还是其它点,均不可达
            //这种情况代表起点至终点无路径
            System.out.println("起点至终点无路径");
            return false;
        } else {
            return true;
        }
    }

    //路径显示
    private void show_path() {
        System.out.print("路径为:");
        System.out.print(end + " ← ");
        //另外创建一个变量 initial_start,记录最初的 start 值
        while (parent[end] != -1 && parent[end] != initial_start) {
            System.out.print(parent[end] + " ← ");
            end = parent[end];
        }
        System.out.print(initial_start);
    }
}

2. 参数说明

private final int num_of_nodes = 9;  	//定义图中节点个数为9个
private int start;  				 	//定义起点编号(代表当前搜索节点,会发生变化)
private int end;  					 	//定义终点编号
private int initial_start;  		 	//定义最初的起点编号
private int biggest; 				 	//定义正无穷
private ArrayList<Integer> point_list;  //定义节点集合
private boolean[] visited;  			//定义各个节点是否被搜索数组
private int[] cal_distance;  			//从最初起点到各个节点当前路径的距离(不一定最短)
private int[] distance;  				//最初起点到当前节点的最短距离数组
private int[] parent;  					//各个节点的父节点(用于路径展示)
private int[][] graph;  				//定义邻接矩阵

3. 演示效果

3.1 起点与终点不重合

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.2 起点与终点重合

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值