Skip to content

Commit

Permalink
修改dijkstra算法实现
Browse files Browse the repository at this point in the history
  • Loading branch information
byhieg committed Apr 7, 2017
1 parent 0b6d1a7 commit cda002d
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 49 deletions.
110 changes: 62 additions & 48 deletions src/main/java/cn/byhieg/algorithmtutorial/GraphMatrix.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cn.byhieg.algorithmtutorial;

import java.util.LinkedList;
import java.util.Queue;
import java.util.*;

/**
* Created by shiqifeng on 2017/4/5.
Expand All @@ -12,7 +11,7 @@ public class GraphMatrix {
Weight[][] graph;
boolean[] isVisited;

private static final int UNREACH = Integer.MAX_VALUE - 1000;
private static final int UNREACH = Integer.MAX_VALUE >> 1;

public GraphMatrix(Weight[][] graph) {
this.graph = graph;
Expand All @@ -23,13 +22,14 @@ public GraphMatrix(Weight[][] graph) {
* 1. 首先将begin节点入队
* 2. 然后判断队列是否为空,不为空,则出队一个元素,输出。
* 3. 将出队的元素的所有相邻的元素且没有访问的都放进队列中,重复第二步
*
* <p>
* 广度优先遍历,从V0出发,访问V0的各个未曾访问的邻接点W1,W2,…,Wk;然后,依次从W1,W2,…,Wk出发访问各自未被访问的邻接点;
*
* @param begin
*/
public void BFS(Integer begin) {
isVisited = new boolean[graph.length];
for (int i = 0 ; i < isVisited.length;i++) {
for (int i = 0; i < isVisited.length; i++) {
isVisited[i] = false;
}

Expand All @@ -40,7 +40,7 @@ public void BFS(Integer begin) {
while (!queue.isEmpty()) {
int current = queue.poll();
System.out.print(current + "-->");
for (int i = 0 ; i < graph[current].length;i++) {
for (int i = 0; i < graph[current].length; i++) {
if (i == begin) {
continue;
}
Expand All @@ -59,11 +59,12 @@ public void BFS(Integer begin) {
* 1. 从begin节点出发,输出begin节点。
* 2. 循环遍历所有与begin节点相邻并且没有被访问的节点
* 3. 找到一个节点,就以他为begin,递归调用DFS
*
* @param begin
*/
public void DFS(Integer begin) {
isVisited = new boolean[graph.length];
for (int i = 0 ; i < isVisited.length;i++) {
for (int i = 0; i < isVisited.length; i++) {
isVisited[i] = false;
}
doDFS(begin);
Expand All @@ -76,72 +77,85 @@ public void DFS(Integer begin) {
* 首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。
* 若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。
* 若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。
*
* @param begin
*/
private void doDFS(Integer begin) {
isVisited[begin] = true;
System.out.print(begin + "-->");
for (int i = 0 ; i < graph[begin].length;i++) {
for (int i = 0; i < graph[begin].length; i++) {
if (graph[begin][i].weight != UNREACH && !isVisited[i]) {
doDFS(i);
}
}
}

public void dijkstra(int start) {
//接受一个有向图的权重矩阵,和一个起点编号start(从0编号,顶点存在数组中)
//返回一个int[] 数组,表示从start到它的最短路径长度
int n = graph.length; //顶点个数
int[] shortPath = new int[n]; //存放从start到其他各点的最短路径
String[] path = new String[n]; //存放从start到其他各点的最短路径的字符串表示
for (int i = 0; i < n; i++)
path[i] = new String(start + "-->" + i);
int[] visited = new int[n]; //标记当前该顶点的最短路径是否已经求出,1表示已求出

//初始化,第一个顶点求出
shortPath[start] = 0;
visited[start] = 1;

for (int count = 1; count <= n - 1; count++) //要加入n-1个顶点
{

int k = -1; //选出一个距离初始顶点start最近的未标记顶点
int dmin = Integer.MAX_VALUE;
for (int i = 0; i < n; i++) {
if (visited[i] == 0 && graph[start][i].weight < dmin) {
dmin = graph[start][i].weight;
/**
* dijkstra 从指定起点到指定终点的最短路
* paths变量,key为节点,value为start到key节点的最短路径
* values变量,key为节点,value为start到key节点的最小值
* 1. dijkstra的核心思想,是广义搜索,先遍历所有与start相邻的节点,且没有找过的点
* 2. 找出最短的节点k,然后以最短的节点为中间节点,如果start-k-i的距离短于start-i,则修改start到i的值,并且修改start到i的路径
* 3. 然后在此基础上,继续从start节点去没有找过的点,重复1
* @param start
* @param end
*/
public void dijkstra(int start, int end) {


int n = graph.length;
isVisited = new boolean[n];
for (int i = 0; i < n; i++) {
isVisited[i] = false;
}
isVisited[start] = true;
HashMap<Integer,String> paths = new HashMap<>();
HashMap<Integer, Integer> values = new HashMap<>();
for(int i = 0 ; i < n;i++) {
if (i == start) {
paths.put(start, start + "");
}else{
paths.put(i, start + "" + i + "");
}
}
values.put(start,0);
while (!values.containsKey(end)) {
int k = -1;
int min = UNREACH;
for (int i = 0; i < n; i++) {
if (!isVisited[i] && graph[start][i].weight < min) {
min = graph[start][i].weight;
k = i;
}

}
//将新选出的顶点标记为已求出最短路径,且到start的最短路径就是dmin
shortPath[k] = dmin;

visited[k] = 1;
values.put(k, min);
isVisited[k] = true;

//以k为中间点,修正从start到未访问各点的距离
for (int i = 0; i < n; i++) { // System.out.println("k="+k);
if (visited[i] == 0 && graph[start][k].weight + graph[k][i].weight < graph[start][i].weight) {
for (int i = 0; i < n; i++) {
if (!isVisited[i] && graph[start][k].weight + graph[k][i].weight < graph[start][i].weight) {
graph[start][i].weight = graph[start][k].weight + graph[k][i].weight;
path[i] = path[k] + "-->" + i;
String path = paths.get(k);
path += i + "";
paths.put(i,path);
}
}
}

for (int i = 0; i < n; i++) {
System.out.println("从" + start + "出发到" + i + "的最短路径为:" + path[i] + " 距离为" + shortPath[i]);
System.out.println("从起始点 " + start + " 到终点 " + end + " 的最短路");
String path = paths.get(end);
for(int i = 0; i < path.length();i++) {
System.out.print(path.charAt(i));
if (i != path.length() - 1){
System.out.print("-->");
}
}
System.out.println("最短路径的值为 " + values.get(end));
}






public static class Weight{
public static class Weight {
int weight;
public Weight(){

public Weight() {
this(UNREACH);
}

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/cn/byhieg/algorithmtutorial/Sort.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package cn.byhieg.algorithmtutorial;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
* Created by shiqifeng on 2017/3/28.
* Mail byhieg@gmail.com
Expand Down Expand Up @@ -202,6 +206,7 @@ public void heapSort(int[] nums) {
// for (int i = 0; i < length; i++) {
// swim(nums, i);
// }
//只能从前一半开始sink
for (int i = length / 2 ; i >= 0;i--) {
sink(nums,i,length);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void testDFS() throws Exception {
}

public void testDijkstra() throws Exception {
graphMatrix.dijkstra(0);
graphMatrix.dijkstra(1,2);
}

}

0 comments on commit cda002d

Please sign in to comment.