/**
* Dijkstra算法(單起點最短路徑) <br/>
* 基於貪婪算法,每次各點到起點的距離中選出最小權重(該值u初始值爲點到起點的距離, 如果點沒有連接起點的邊,則值爲正無窮)的點n加入到樹中
* ,新加入點應該有一個值記錄到起點的距離d,在遍歷剩下未加入樹的點,如果當前點u值大於新加入點n到當前點的距離d1+d,
* 則當前點將更新爲d1+d,如此重複,直至全部點加入樹
*
* <br/>
* 每個節點必須有兩個標記:(1)起點到頂點的最短路徑 (2)頂點父母 <br/>
* <br/>
* 加入樹中的節點u*後: <br/>
* (1)把u*從邊緣集合中移動到樹頂點集合 <br/>
* (2)對餘下的每一個邊緣節點u,如果通過權重w(u*,u)的邊和u*相連,當du* + w(u*,u) < du時,把u的標記分別更新爲du* +
* w(u*,u)
*
* @author chenxuegui
*
*/
public class Dijkstra
{
// 存儲未加入樹的節點同樹中點的最小距離
private static Map<String, Distance> map;
// 存儲加入的邊
private static List<Distance> tree;
private static String origin = null;
public static void main(String[] args)
{
int[][] a = new int[5][5];
tree = new ArrayList<>();
map = new HashMap<>();
String cur = null;
init(args, a, 5);
cur = origin;
int preDis = 0;
map.remove(origin);
while (map.size() != 0)
{
traverse(cur, a, 5, preDis);
Distance minDis = find();
tree.add(minDis);
cur = minDis.getVertex();
preDis = minDis.getWeight();
}
System.out.println(tree);
}
/**
* 初始化
*/
private static void init(String args[], int[][] a, int n)
{
int i = 0;
for (; i < n * n; i++)
{
a[i / n][i % n] = Integer.valueOf(args[i]);
}
origin = args[i++];
n += i;
for (; i < n; i++)
{
map.put(args[i], new Distance(args[i], null, Integer.MAX_VALUE));
System.out.println(args[i]);
}
}
/**
* 從Map<String, Distance>中查找權值最小的關係對應的邊 返回邊
*
* @return
*/
public static Distance find()
{
String key = null;
int minWeight = Integer.MAX_VALUE;
for (Entry<String, Distance> entry : map.entrySet())
{
if (minWeight > entry.getValue().getWeight())
{
key = entry.getKey();
minWeight = entry.getValue().getWeight();
}
}
// 約束:把map.key(未加入樹的點)放在vertex1
Distance d = map.get(key);
map.remove(key);
return d;
}
/**
* 從cur vertex中對各既在map中又在權值比map中小的點跟新到map中
*
* @param vertex
* 上一個加入map的節點
* @param a
* @param n
* @param preDis
* 上一個節點到起點的距離
*/
public static void traverse(String vertex, int[][] a, int n, int preDis)
{
Distance distance;
String s;
int index = vertex.charAt(0) - 97;
for (int i = 0; i < n; i++)
{
s = "" + (char) (i + 97);
if (i != index && map.get(s) != null)
{
distance = map.get(s);
if (distance.getWeight() > a[index][i] + preDis
&& a[index][i] != 0)
{
distance.setWeight(a[index][i] + preDis);
distance.setParentVertex(vertex);
}
}
}
}
}
/**
*
* @author Administrator
*
*/
class Distance
{
/**
* 該節點
*/
private String vertex;
/**
* 該節點的父節點,即與當前節點連着的邊的另一個節點
*/
private String parentVertex;
/**
* 兩個點所在邊的權值
*/
private int weight;
public Distance(String vertex, String parentVertex, int weight)
{
this.vertex = vertex;
this.parentVertex = parentVertex;
this.weight = weight;
}
public String toString()
{
return "(" + this.parentVertex + " : " + this.vertex + "value: "
+ this.getWeight() + ")";
}
public String getVertex()
{
return vertex;
}
public void setVertex(String vertex)
{
this.vertex = vertex;
}
public String getParentVertex()
{
return parentVertex;
}
public void setParentVertex(String parentVertex)
{
this.parentVertex = parentVertex;
}
public int getWeight()
{
return weight;
}
public void setWeight(int weight)
{
this.weight = weight;
}
}