frankdevhub

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::


  本文为博主原创文章,未经博主允许不得转载!

 

1.1、定义概览
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。

问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)

1.2、算法描述
1)算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

2)算法步骤:
a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。
b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
d.重复步骤b和c直到所有顶点都包含在S中。

 

 

实现:

  1 public class GraphByMatrix {  
  2     public static final boolean UNDIRECTED_GRAPH = false;//无向图标志  
  3     public static final boolean DIRECTED_GRAPH = true;//有向图标志  
  4   
  5     public static final boolean ADJACENCY_MATRIX = true;//邻接矩阵实现  
  6     public static final boolean ADJACENCY_LIST = false;//邻接表实现  
  7   
  8     public static final int MAX_VALUE = Integer.MAX_VALUE;  
  9     private boolean graphType;  
 10     private boolean method;  
 11     private int vertexSize;  
 12     private int matrixMaxVertex;  
 13   
 14     //存储所有顶点信息的一维数组  
 15     private Object[] vertexesArray;  
 16     //存储图中顶点之间关联关系的二维数组,及边的关系  
 17     private int[][] edgesMatrix;  
 18   
 19     // 记录第i个节点是否被访问过  
 20     private boolean[] visited;  
 21   
 22     /** 
 23      * @param graphType 图的类型:有向图/无向图 
 24      * @param method    图的实现方式:邻接矩阵/邻接表 
 25      */  
 26     public GraphByMatrix(boolean graphType, boolean method, int size) {  
 27         this.graphType = graphType;  
 28         this.method = method;  
 29         this.vertexSize = 0;  
 30         this.matrixMaxVertex = size;  
 31   
 32         if (this.method) {  
 33             visited = new boolean[matrixMaxVertex];  
 34             vertexesArray = new Object[matrixMaxVertex];  
 35             edgesMatrix = new int[matrixMaxVertex][matrixMaxVertex];  
 36   
 37             //对数组进行初始化,顶点间没有边关联的值为Integer类型的最大值  
 38             for (int row = 0; row < edgesMatrix.length; row++) {  
 39                 for (int column = 0; column < edgesMatrix.length; column++) {  
 40                     edgesMatrix[row][column] = MAX_VALUE;  
 41                 }  
 42             }  
 43   
 44         }  
 45     }  
 46   
 47     /********************最短路径****************************/  
 48     //计算一个顶点到其它一个顶点的最短距离  
 49     public void Dijkstra(Object obj) throws Exception {  
 50         Dijkstra(getVertexIndex(obj));  
 51     }  
 52     public void Dijkstra(int v0) {  
 53         int[] dist = new int[matrixMaxVertex];  
 54         int[] prev = new int[matrixMaxVertex];  
 55   
 56         //初始化visited、dist和path  
 57         for (int i = 0; i < vertexSize; i++) {  
 58             //一开始假定取直达路径最短  
 59             dist[i] = edgesMatrix[v0][i];  
 60             visited[i] = false;  
 61   
 62             //直达情况下的最后经由点就是出发点  
 63             if (i != v0 && dist[i] < MAX_VALUE)  
 64                 prev[i] = v0;  
 65             else  
 66                 prev[i] = -1; //无直达路径  
 67         }  
 68   
 69         //初始时源点v0∈visited集,表示v0 到v0的最短路径已经找到  
 70         visited[v0] = true;  
 71   
 72         // 下来假设经由一个点中转到达其余各点,会近些,验证之  
 73         // 再假设经由两个点中转,会更近些,验证之,.....  
 74         // 直到穷举完所有可能的中转点  
 75         int minDist;  
 76         int v = 0;  
 77         for (int i = 1; i < vertexSize; i++) {  
 78             //挑一个距离最近经由点,下标装入 v  
 79             minDist = MAX_VALUE;  
 80   
 81             for (int j = 0; j < vertexSize; j++) {  
 82                 if ((!visited[j]) && dist[j] < minDist) {  
 83                     v = j;                             // 经由顶点j中转则距离更短  
 84                     minDist = dist[j];  
 85                 }  
 86             }  
 87             visited[v] = true;  
 88   
 89             /*顶点v并入S,由v0到达v顶点的最短路径为min. 
 90               假定由v0到v,再由v直达其余各点,更新当前最后一个经由点及距离*/  
 91             for (int j = 0; j < vertexSize; j++) {  
 92                 if ((!visited[j]) && edgesMatrix[v][j] < MAX_VALUE) {  
 93   
 94                     if (minDist + edgesMatrix[v][j] <= dist[j]) {  
 95                         //如果多经由一个v点到达j点的 最短路径反而要短,就更新  
 96                         dist[j] = minDist + edgesMatrix[v][j];  
 97   
 98                         prev[j] = v;                    //经由点的序号  
 99                     }  
100   
101                 }  
102             }  
103   
104         }  
105   
106         for (int i = 1; i < matrixMaxVertex; i++) {  
107             System.out.println("**" + vertexesArray[v0] + "-->" +vertexesArray[i] + " 的最短路径是:" + dist[i]);  
108         }  
109     }  
110   
111     //获取顶点值在数组里对应的索引  
112     private int getVertexIndex(Object obj) throws Exception {  
113         int index = -1;  
114         for (int i = 0; i < vertexSize; i++) {  
115             if (vertexesArray[i].equals(obj)) {  
116                 index = i;  
117                 break;  
118             }  
119         }  
120         if (index == -1) {  
121             throw new Exception("没有这个值!");  
122         }  
123   
124         return index;  
125     }  
126   
127     /** 
128      * 单源最短路径算法,用于计算一个节点到其他!!所有节点!!的最短路径 
129      */  
130     public void Dijkstra2(int v0) {  
131         // LinkedList实现了Queue接口 FIFO  
132         Queue<Integer> queue = new LinkedList<Integer>();  
133         for (int i = 0; i < vertexSize; i++) {  
134             visited[i] = false;  
135         }  
136   
137         //这个循环是为了确保每个顶点都被遍历到  
138         for (int i = 0; i < vertexSize; i++) {  
139             if (!visited[i]) {  
140                 queue.add(i);  
141                 visited[i] = true;  
142   
143                 while (!queue.isEmpty()) {  
144                     int row = queue.remove();  
145                     System.out.print(vertexesArray[row] + "-->");  
146   
147                     for (int k = getMin(row); k >= 0; k = getMin(row)) {  
148                         if (!visited[k]) {  
149                             queue.add(k);  
150                             visited[k] = true;  
151                         }  
152                     }  
153   
154                 }  
155             }  
156         }  
157     }  
158   
159     private int getMin( int row) {  
160         int minDist = MAX_VALUE;  
161         int index = 0;  
162         for (int j = 0; j < vertexSize; j++) {  
163             if ((!visited[j]) && edgesMatrix[row][j] < minDist) {  
164                 minDist = edgesMatrix[row][j];  
165                 index = j;  
166             }  
167         }  
168         if (index == 0) {  
169             return -1;  
170         }  
171         return index;  
172     }  
173   
174     public boolean addVertex(Object val) {  
175         assert (val != null);  
176         vertexesArray[vertexSize] = val;  
177         vertexSize++;  
178         return true;  
179     }  
180   
181     public boolean addEdge(int vnum1, int vnum2, int weight) {  
182         assert (vnum1 >= 0 && vnum2 >= 0 && vnum1 != vnum2 && weight >= 0);  
183   
184         //有向图  
185         if (graphType) {  
186             edgesMatrix[vnum1][vnum2] = weight;  
187   
188         } else {  
189             edgesMatrix[vnum1][vnum2] = weight;  
190             edgesMatrix[vnum2][vnum1] = weight;  
191         }  
192   
193         return true;  
194     }  
195   
196 }  

测试

 

 1 @Test  
 2 public void testWeight() throws Exception {  
 3     GraphByMatrix graph = new GraphByMatrix(Graph.UNDIRECTED_GRAPH, Graph.ADJACENCY_MATRIX, 6);  
 4   
 5     graph.addVertex("1");  
 6     graph.addVertex("2");  
 7     graph.addVertex("3");  
 8     graph.addVertex("4");  
 9     graph.addVertex("5");  
10     graph.addVertex("6");  
11   
12     graph.addEdge(0, 1,7);  
13     graph.addEdge(0, 2,9);  
14     graph.addEdge(0, 5,14);  
15   
16     graph.addEdge(1, 3,15);  
17     graph.addEdge(1, 2,10);  
18   
19     graph.addEdge(2, 3,11);  
20     graph.addEdge(2, 5,2);  
21   
22     graph.addEdge(3, 4,6);  
23     graph.addEdge(4, 5,9);  
24   
25     graph.Dijkstra(0);  
26     System.out.println();  
27     graph.Dijkstra("1");  
28     System.out.println();  
29     graph.Dijkstra2(0);  
30     System.out.println();  
31 }  

 

posted on 2017-08-20 19:36  frankdevhub  阅读(760)  评论(0编辑  收藏  举报