感谢每一位朋友的阅读与建议,今天对最短路径blog进行了修改,调整图和部分内容。感谢各位关注。提早祝大家圣诞节平安快乐。
给定一个带权有向图G=(V,E),其中每条边的权是一个实数。另外,还给定V中的一个顶点,称为源。现在要计算从源到其他所有各顶点的最短路径长度。这里的长度就是指路上各边权之和。这个问题通常称为单源最短路径问题
借助队列实现每条边只访问一次。
/**
* 无权最短路径
*
* @param s 起点
*/
public void unweight(Vertex s) {
Queue<Vertex> q = new LinkedList<Vertex>();
for (Vertex x : graph) {
//每个节点的初始最短路径为Integer的最大值,表示该节点的最短路径未知
x.setDist(Integer.MAX_VALUE);
}
s.dist = 0;
q.add(s);
while (!q.isEmpty()) {
Vertex v = q.poll();
if (v != null) {
if (v.getAdj() != null && !v.getAdj().isEmpty()) {
for (Vertex w : v.getAdj()) {
if (w.getDist() == Integer.MAX_VALUE) {//每条边只访问一次
w.setDist(v.getDist()+1);
w.setPath(v);
q.add(w);
}
}
}
}
}
}
O(|E|+|V|)
Dijkstra算法是解决有权无负值单源最短路径的经典算法。
/**
* 著名的dijkstra算法 解决单源最短路径(权无负值)
*
* @param s
* 起点
*/
public void dijkstra(Vertex s) {
for (Vertex v : graph) {// 初始默认所有顶点未被访问
v.setDist(Integer.MAX_VALUE);
v.known = false;
}
s.dist = 0;// 声明起点的距离为0
PriorityQueue<Vertex> priorityQueue = new PriorityQueue<Vertex>();
// 将s放入优先队列
priorityQueue.add(s);
while (!priorityQueue.isEmpty()) {// 知道所有顶点的最短路径都已知并且优先队列为空
Vertex v = priorityQueue.poll();// 取出未知节点中最短路径最小的节点
if (v != null) {
if (!v.known) {
v.known = true;// 声明该节点已知
if (v.getAdj() != null && !v.getAdj().isEmpty()) {
// 如 dv+cvw<=dw 则更新临接点的最短路径,并且更新值放入到优先队列中
for (AdjVertex adjW : v.getAdj()) {
if (!adjW.getW().known) {
if (v.dist + adjW.cvw < adjW.getW().getDist()) {
adjW.getW().setDist(v.dist + adjW.cvw);
adjW.getW().setPath(v);
priorityQueue.add(adjW.getW());
}
}
}
}
}
}
}
}
针对一个有权图,该图的权有负值,使用某个顶点s作为输入参数,找出该顶点s到其他顶点的最短距离。
借助广度优先搜素实现。
/**
* 有权有负值最短路径
* 借助广度优先搜素
* @param s 起点
*/
public void weightNegative(Vertex s) {
Queue<Vertex> q = new LinkedList<Vertex>();
for (Vertex v : graph) {
v.dist = Integer.MAX_VALUE;
v.isInQueue = false;
}
s.dist = 0;
s.isInQueue = true;
q.add(s);
while (!q.isEmpty()) {
Vertex v = q.poll();
v.isInQueue = false;
if (v.getAdj() != null && !v.getAdj().isEmpty()) {
for (AdjVertex wadj : v.getAdj()) {
if (wadj.cvw + v.dist < wadj.getW().dist) {
wadj.getW().setDist(wadj.cvw + v.dist);
wadj.getW().setPath(v);
if (!wadj.getW().isInQueue) {
wadj.getW().isInQueue = false;
q.add(wadj.getW());
}
}
}
}
}
}
O(|E|*|V|)
O(|E|+|V|)
O(|E|*|V|)