带权图最短路径

本文介绍了一个使用Dijkstra算法计算图中两点间最短路径的Java实现。通过定义顶点类和距离父节点类,该算法能够计算从指定起点到图中其他所有顶点的最短路径,并记录沿途经过的父节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


//Dijkstra算法求2点间最短路径,其实这里显示了从起点到所有其他点的最短距离
//存储父节点和距离
class DistPar {
    int distance;
    int parentVer;

    public DistPar(int parentVer, int distance) {
        this.distance = distance;
        this.parentVer = parentVer;
    }
}

// 顶点
class Vertex_2 {
    char label;
    boolean inTree;

    public Vertex_2(char label) {
        this.label = label;
        inTree = false;
    }
}

public class MinDistance {
    private final int maxVer;
    private final int INFINITY = 100000;// 没有边
    private int nvers;// 顶点数
    private int curVer;// 当前顶点index
    private int nTree;// 树中顶点数
    private Vertex_2[] vertex;
    private int[][] adjMat;
    private DistPar[] spath;
    private int startToCur;// 开始到当前距离

    public MinDistance(int size) {
        maxVer = size;
        nvers = 0;
        nTree = 0;
        vertex = new Vertex_2[maxVer];
        adjMat = new int[maxVer][maxVer];
        for (int i = 0; i < maxVer; i++)
            for (int j = 0; j < maxVer; j++)
                adjMat[i][j] = INFINITY;
        spath = new DistPar[maxVer];
    }

    public void addVer(char label) {
        vertex[nvers++] = new Vertex_2(label);
    }

    public void addEdge(int start, int end, int distance) {
        adjMat[start][end] = distance;
    }

    public void path(int index) {
        int startTree = index;// 书上直接设置起点为0
        vertex[startTree].inTree = true;
        nTree = 1;
        for (int j = 0; j < nvers; j++) {
            int tempDist = adjMat[startTree][j];
            spath[j] = new DistPar(startTree, tempDist);
        }
        while (nTree < nvers) {
            int indexMin = getMin();
            int minDist = spath[indexMin].distance;
            if (minDist == INFINITY) {// 如果都为INFINITY或都在树中了,正常时下面语句也可能会输出
                System.out.println("unreachable vertices");
                break;
            } else {
                curVer = indexMin;
                startToCur = spath[indexMin].distance;
            }
            vertex[curVer].inTree = true;
            nTree++;
            adjust_path();
        }
        displayPath();
        // 重置
        nTree = 0;
        for (int j = 0; j < nvers; j++)
            vertex[j].inTree = false;
    }

    // 显示距离和起点到终点经过的父节点
    private void displayPath() {
        for (int j = 0; j < nvers; j++) {
            if (spath[j].distance == INFINITY)
                System.out.print(" inf");
            else
                System.out.print(spath[j].distance);
            char parent = vertex[spath[j].parentVer].label;
            System.out.print("-" + parent + "  ");
        }
        System.out.println();
    }
//核心部分
    private void adjust_path() {
        int column = 0;// 书上为1
        while (column < nvers) {
            if (vertex[column].inTree) {
                column++;
                continue;
            }
            int curToFringe = adjMat[curVer][column];
            int startToFringe = curToFringe + startToCur;
            int spathDist = spath[column].distance;
            if (startToFringe < spathDist) {
                spath[column].parentVer = curVer;
                spath[column].distance = startToFringe;
            }
            column++;
        }

    }

    private int getMin() {
        int minDist = INFINITY;
        int indexMin = 0;
        for (int i = 0; i < nvers; i++) {// 书上i从1开始,这2个地方修改下可以从任意顶点开始
            if (!vertex[i].inTree && spath[i].distance < minDist) {
                minDist = spath[i].distance;
                indexMin = i;
            }
        }
        return indexMin;
    }

    public static void main(String[] args) {
        MinDistance min = new MinDistance(20);
        min.addVer('A');
        min.addVer('B');
        min.addVer('C');
        min.addVer('D');
        min.addVer('E');
        min.addEdge(0, 1, 50);
        min.addEdge(0, 3, 80);
        min.addEdge(1, 2, 60);
        min.addEdge(1, 3, 90);
        min.addEdge(2, 4, 40);
        min.addEdge(3, 2, 20);
        min.addEdge(3, 4, 70);
        min.addEdge(4, 1, 50);
        min.path(0);//  inf-A  50-A  100-D  80-A  140-C 
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值