Java--单源最短路径问题

单源最短路径问题

  • 一、实验目的:
  • 二、实验内容及要求:
  • 三、实验原理:
  • 四、源代码

一、实验目的:

1、理解分支限界法的剪枝搜索策略;
2、掌握分支限界法的算法柜架;
3、掌握分支限界法的算法步骤;
4、通过应用范例学习动态规划算法的设计技巧与策略;

二、实验内容及要求:

1、使用分支限界法解决单源最短路径问题。
2、通过上机实验进行算法实现。
3、保存和打印出程序的运行结果,并结合程序进行分析,上交实验报告。

三、实验原理:

1.创建一个实现Comparable接口的节点类HeapNode,该类具有两个属性,分别是节点编号index和源点到该节点的最短距离length。同时在该类中重写compareTo方法,使用最短距离length属性作为比较条件,从小到大排序。

2.函数shortest()开始创建一个LinkedList对象,元素类型为HeapNode类,由于其本质是一个双向链表且元素HeapNode类具有compareTo方法,因此可以充当优先级队列。将各顶点的最短距离赋值为Float.MAX_VALUE,完成初始化工作。While循环完成最短距离的更新工作,对于当前的扩展结点, 依次检查与之相邻的所有顶点。如果从源点经顶点node到顶点i的路径长度小于当前的最短距离,就更新顶点i的最短距离并将顶点node作为顶点i的前趋节点,将顶点i加入到链表对象中,重新进行链表排序,找到当前距离源点最近的顶点,最后取出链表中的头节点,实现扩展结点更新。当链表为空时,退出循环,得到最短距离。

四、源代码

import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;

public class ShortestPath {
    /**
     * 节点类
     */
    private static class HeapNode implements Comparable {
        // 当前节点的编号
        private int index;
        // 当前到达此节点的最短距离
        private float length;

        public HeapNode(int index,float length) {
            this.index = index;
            this.length = length;
        }

        /**
         * 重写compareTo方法,便于排序使用
         * @param object : 另一个节点
         * @return
         */
        @Override
        public int compareTo(Object object) {
            float len = ((HeapNode) object).length;
            return (length < len) ? 1:0;
        }
    }

    /**
     *  分支限界(单源最短路径)
     * @param a : 两点间的距离数组
     * @param dist : 当前最短距离数组
     * @param origin : 源点编号
     * @param prev : 前趋节点数组
     */
    public static void shortest(float[][] a,float[] dist,int origin,int[] prev) {
        // 顶点数量
        int n = prev.length - 1;
        // 创建节点链表
        LinkedList<HeapNode> nodes = new LinkedList<>();
        // 创建源节点
        HeapNode node = new HeapNode(origin,0);
        for (int i = 1;i <= n;++i) {
            // 初始化最短距离为Float.MAX_VALUE
            dist[i] = Float.MAX_VALUE;
        }
        while (true) {
            for (int i = 1;i <= n;++i) {
                // 两节点间存在路径且到节点node的距离加两点间距离小于当前到节点i的最短距离
                if (a[node.index][i] != -1 && node.length + a[node.index][i] < dist[i]) {
                    // 更新当前到节点i的最短距离
                    dist[i] = node.length + a[node.index][i];
                    // 更新节点i的前趋节点
                    prev[i] = node.index;
                    // 创建节点i对象
                    HeapNode heapNode = new HeapNode(i,dist[i]);
                    // 添加到链表中
                    nodes.add(heapNode);
                    // 按距离从短到长排序
                    Collections.sort(nodes);
                }
            }
            // 链表为空退出循环
            if (nodes.isEmpty()) {
                break;
            }else {
                // 取出当前距离源点最近的节点
                node = nodes.poll();
            }
        }
        // 输出结果
        for (int i = 2;i <= n;++i) {
            System.out.println(i+"节点的最短距离是:"+dist[i]+";前驱点是:"+prev[i]);
        }
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("请输入图的顶点数:");
        // 创建顶点数量
        int n = in.nextInt();
        // 消除回车键影响
        in.nextLine();
        // 创建前趋节点数组
        int[] prev = new int[n+1];
        // 创建两点间距离数组
        float[][] a = new float[n+1][n+1];
        // 创建最短距离数组
        float[] dist = new float[n+1];
        System.out.println("请输入图的路径长度:");
        for (int i = 0;i < n;++i) {
            // 获得一行内容
            String line = in.nextLine();
            //将一个顶点到其他顶点的距离转成距离数组
            String[] length = line.split(",");
            for (int j = 0;j < length.length;++j) {
                // 赋值
                a[i+1][j+1] = Float.parseFloat(length[j]);
            }
        }
        // 调用最短路径算法
        shortest(a,dist,1,prev);
        in.close();
    }
}

你可能感兴趣的:(Java,java)