zoukankan      html  css  js  c++  java
  • Dijkstra算法与最短路径问题

    @author:QYX 最近两三个周,肝完了一个开源项目,看完了webkit技术内幕和Devlops的书,收获不错

    继续搬运更新!

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

    基本思想
    通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。

    此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。

    初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是”起点s到该顶点的路径”。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 … 重复该操作,直到遍历完所有顶点。

    操作步骤
    初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为”起点s到该顶点的距离”[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。

    从U中选出”距离最短的顶点k”,并将顶点k加入到S中;同时,从U中移除顶点k。

    更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。

    重复步骤(2)和(3),直到遍历完所有顶点。

     

     

     

     

     

    package com.qyx.Tree;
    
    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,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.dsj(6);
            graph.show();
        }
    }
    class Graph{
        private char[] vertex;//顶点数组
        private int[][] matrix;//邻接矩阵
        private VisitedVertex vv;//已经访问的顶点集合
        public void show()
        {
            vv.show();
        }
        //构造器
        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));
            }
        }
        //迪杰斯特拉算法那实现
        /**
         * 
         * @param index 表示出发节点对应下标
         */
        public void dsj(int index)
        {
            vv=new VisitedVertex(vertex.length, index);
            update(index);
            for(int j=1;j<vertex.length;j++)
            {
                index=vv.updateArr();//选择并返回新的访问节点
                update(index);//更新index下标顶点到周围顶点的距离和周围顶点的前驱顶点
            }
        }
        //更新index下标顶点到周围顶点的距离和周围顶点的前驱顶点
        private void update(int index)
        {
            int len=0;
            //根据遍历我们的邻接矩阵的matrix[index]行
            for(int j=0;j<matrix[index].length;j++)
            {
                //len的含义是出发顶点到index顶点的距离+从index顶点到j顶点的距离的和
                len=vv.getDis(index)+matrix[index][j];
                //如果j顶点没有被访问过,并且len小于出发顶点到j顶点的距离就需要更新 G->A->B
                if(!vv.in(j)&&len<vv.getDis(j))
                {
                    vv.updatePre(j, index);//更新j顶点的前驱为index顶点
                    vv.updateDis(j, len);//更新出发顶点到j顶点的距离
                }
            }
        }
    }
    //已访问顶点集合
    class VisitedVertex{
        
        //记录各个顶点是否被访问过,1表示访问过,0表示未访问,会动态更新
        public int[] aleady_arr;
        //每个下标对应的值的前一个顶点下标,会动态更新
        public int[] pre_visited;
        //记录出发顶点到其他所有顶点的距离,比如G为出发顶点,就会记录G到其他顶点距离,会动态更新,求得最短距离就会存放到dis
        public int[] dis;
        //构造器
        /**
         * 
         * @param length 表示顶点个数
         * @param index 表示出发顶点对应的下标,比如G顶点,下标就是6
         */
        public VisitedVertex(int length,int index)
        {
            this.aleady_arr=new int[length];
            this.pre_visited=new int[length];
            this.dis=new int[length];
            //初始化dis数组
            Arrays.fill(dis,65535);
            this.aleady_arr[index]=1;//设置出发顶点被访问过
            this.dis[index]=0;//设置出发顶点的访问距离为0
        }
        /**
         * 功能:判断index顶点是否被访问过
         * @param index 
         * @return 如果访问过就返回true,否则返回false
         */
        public boolean in(int index)
        {
            return aleady_arr[index]==1;
        }
        /**
         * 功能:更新出发顶点到index顶点的距离
         * @param index 
         * @param len
         */
        public void updateDis(int index,int len)
        {
            dis[index]=len;
        }
        /**
         * 功能:更新顶点的前驱为index结点
         * @param pre
         * @param index
         */
        public void updatePre(int pre,int index)
        {
            pre_visited[pre]=index;
        }
        /**
         * 返回出顶定点到index顶点的距离
         * @param index
         * @return 
         */
        public int getDis(int index)
        {
            return dis[index];
        }
        //继续选择并返回新的访问顶点,比如这里的G访问完后,就是A点作为新的访问顶点(注意不是出发顶点)
            public int updateArr()
            {
                int min=65535,index=0;
                for(int i=0;i<aleady_arr.length;i++)
                {
                    if(aleady_arr[i]==0 && dis[i]<min)
                    {
                        min=dis[i];
                        index=i;
                    }
                }
                aleady_arr[index]=1;
                return index;
            }
        //显示最后的结果
        //即将三个数组输出
            public void show()
            {
                System.out.println("================================");
                for(int i : aleady_arr)
                {
                    System.out.print(i+" ");
                }
                System.out.println();
                for(int i:pre_visited)
                {
                    System.out.print(i+" ");
                }
                System.out.println();
                for(int i:dis)
                {
                    System.out.print(i+" ");
                }
                System.out.println();
                char[] vertex={'A','B','C','D','E','F','G'};
                int count=0;
                for(int i:dis)
                {
                    if(i!=65535)
                    {
                        System.out.print(vertex[count]+"("+i+")");
                    }
                    count++;
                }
                System.out.println();
            }
    }
  • 相关阅读:
    PHP AES256加密算法
    PHP字符串比较
    linux常用命令
    播放音乐方法(兼容IE FF Chrome Opera Safari)
    JS小游戏象棋暗棋
    Sublime Text 2 介紹
    php生成QRcode
    几种极其隐蔽的XSS注入的防护
    JS判断碰撞方法
    php 发送带附件邮件
  • 原文地址:https://www.cnblogs.com/qyx66/p/12506594.html
Copyright © 2011-2022 走看看