栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

第十四章:常用的十大算法

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第十四章:常用的十大算法

14.8迪杰斯特拉算法(Dijkstra)

Dijkstra算法介绍:
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个结点到其他结点的最短路径。它的主要特点是以 起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止

Dijkstra算法思路:
1、 设置出发顶点为 v,顶点集合 V{v1,v2,vi…},v 到 V 中各顶点的距离构成距离集合 Dis,Dis{d1,d2,di…},Dis 集合记录着 v 到图中各顶点的距离(到自身可以看作 0,v 到 vi距离对应为di)
2、 从 Dis 中选择值最小的 di 并移出 Dis 集合,同时移出 V 集合中对应的顶点 vi,此时的 v 到 vi 即为最短路径
3、 更新 Dis 集合,更新规则为:比较 v 到 V 集合中顶点的距离值,与 v 通过 vi 到 V 集合中顶点的距离值,保留 值较小的一个(同时也应该更新顶点的前驱节点为 vi,表明是通过 vi 到达的)
4、 重复执行两步骤,直到最短路径顶点为目标顶点即可结束

Dijkstra算法应用:寻找指定村庄到其他各个村庄的最短路径问题

package com.atguigu21.dijkstra;

import java.util.Arrays;


public class DijkstraAlgorithm {
    public static void main(String[] args) {
        char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        final int N = 65535;
        int[][] matrix = new int[vertex.length][vertex.length];
        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, N};
        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.dis(6);
        graph.showDijkstra();
    }
}


class VisitedVertexs {
    public int[] alread_arr;//记录每个结点是否已经访问过,如果访问过就置为1, 没有访问过就是0
    public int[] pre_visited;//记录每一个结点对应的前一个结点的下标,也就是每一个结点的前驱结点
    public int[] dis;//记录出发顶点到其它结点的距离,比如:假设出发顶点是G,那么dis保留的就是G到其它结点的距离

    
    public VisitedVertexs(int length, int index) {
        this.alread_arr = new int[length];
        this.pre_visited = new int[length];
        this.dis = new int[length];

        //初始化距离
        Arrays.fill(dis, 65535);//表示刚开始的时候,所有点之间的距离都是65535
        dis[index] = 0;//表示自己到自己的距离是0,并不是65535
        this.alread_arr[index] = 1;//当前结点一进来就表示已经遍历了,所以要置为1
    }

    
    public boolean ifVisited(int index) {
        return alread_arr[index] == 1;
    }

    
    public void updateDis(int inedx, int len) {
        dis[inedx] = len;
    }

    
    public void updatePre(int pre, int index) {
        pre_visited[pre] = index;
    }

    
    public int getDis(int index) {
        return dis[index];
    }

    
    public int updateArr() {
        int min = 65535, index = 0;
        for (int i = 0; i < alread_arr.length; i++) {
            if (alread_arr[i] == 0 && dis[i] < min) {
                //如果发现了新的更加短的路径
                index = i;
                min = dis[i];
            }
        }
        alread_arr[index] = 1;
        return index;
    }

    
    public void show() {
        for (int row : alread_arr) {
            System.out.print(row + "t");
        }
        System.out.println();
        for (int value : pre_visited) {
            System.out.print(value + "t");
        }
        System.out.println();
        for (int value : dis) {
            System.out.print(value + "t");
        }
    }
}


class Graph {
    private char[] vertex;//图的顶点
    private int[][] matrix;//二维数组
    private VisitedVertexs vv;//已经访问过的顶点的集合

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

    
    public void showGraph() {
        for (int[] row : matrix) {
            System.out.println(Arrays.toString(row));
        }
    }

    
    public void dis(int index) {
        vv = new VisitedVertexs(vertex.length, index);
        update(index);
        for (int i = 1; i < vertex.length; i++) {
            //因为顶点已经进去了,所以从下一个点开始
            index = vv.updateArr();
            update(index);
        }
    }

    
    public void update(int index) {
        int len = 0;
        //遍历index结点对应的行
        for (int i = 0; i < matrix[index].length; i++) {
            //vv.getDis(index):表示当前结点之前,已经走过的距离
            //matrix[index][i]:表示当前结点到下一个结点的距离
            len = vv.getDis(index) + matrix[index][i];
            if (!vv.ifVisited(i) && len < vv.getDis(i)) {
                //如果发现这一条新的路,比原来的那一条路还要近,就要用新路去替换旧路
                vv.updateDis(i, len);//更新出发顶点到i的距离
                vv.updatePre(i, index);//将i结点的前驱更改为index
            }
        }
    }

    public void showDijkstra() {
        vv.show();
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/656622.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号