加权有向边代码:
package com.chenqing.test.digraph;
/**
* @author 陈沁
* 加权有向图的边
*/
public class DirectEdge {
private Double weight;
private int from;
private int to;
public DirectEdge(Double weight, int from, int to) {
this.weight = weight;
this.from = from;
this.to = to;
}
public Double getWeight() {
return weight;
}
public int getFrom() {
return from;
}
public int getTo() {
return to;
}
}
加权有向图代码:
package com.chenqing.test.digraph;
import com.chenqing.test.linearList.queue.Queue;
/**
* @author 陈沁
* 加权有向图
*/
public class EdgeWeightedDirectGraph {
private final int v;
private int e;
private Queue<DirectEdge>[] edgeQueue;
public EdgeWeightedDirectGraph(int v) {
this.v = v;
this.e = 0;
this.edgeQueue = new Queue[v];
for (int i = 0; i < v; i++) {
this.edgeQueue[i] = new Queue<DirectEdge>();
}
}
public int getV(){
return v;
}
public int getE(){
return e;
}
public void addEdge(DirectEdge edge){
int from = edge.getFrom();
this.edgeQueue[from].enqueue(edge);
e++;
}
public Queue<DirectEdge> adj(int v){
return edgeQueue[v];
}
public Queue<DirectEdge> edges(){
Queue<DirectEdge> edges = new Queue<>();
for (int i = 0; i < v; i++) {
for (DirectEdge edge : edgeQueue[i]) {
edges.enqueue(edge);
}
}
return edges;
}
}
Dijkstra算法:
package com.chenqing.test.digraph;
import com.chenqing.test.linearList.queue.IndexMinPriorityxQueue;
import com.chenqing.test.linearList.queue.Queue;
/**
* @author 陈沁
* 使用Dijkstra实现最短路径
*/
public class DijkstraSP {
private DirectEdge[] edgeTo; //索引代表顶点,值代表从顶点s到当前顶点的最短路径上的最后一条边
private Double[] distTo; //索引代表顶点,值代表从顶点s到当前顶点的最短路径的总权重
private IndexMinPriorityxQueue<Double> indexMinPriorityxQueue; //存放树中顶点与非树中顶点之间的有效横切边
public DijkstraSP(EdgeWeightedDirectGraph graph, int s) {
this.edgeTo = new DirectEdge[graph.getV()];
this.distTo = new Double[graph.getV()];
this.indexMinPriorityxQueue = new IndexMinPriorityxQueue<>(graph.getV());
for (int i = 0; i < this.distTo.length; i++) {
this.distTo[i] = Double.POSITIVE_INFINITY;
}
this.distTo[0] = 0.0;
this.indexMinPriorityxQueue.insert(0, 0.0);
while (!this.indexMinPriorityxQueue.isEmpty()){
int minIndex = this.indexMinPriorityxQueue.delMin();
this.relax(graph, minIndex);
}
}
/**
* 松驰图中的v顶点
* @param graph
* @param v
*/
private void relax(EdgeWeightedDirectGraph graph, int v){
Queue<DirectEdge> adj = graph.adj(v);
for (DirectEdge edge : adj) {
int to = edge.getTo();
if(distTo(v) + edge.getWeight() < distTo(to)){
distTo[to] = distTo[v] + edge.getWeight();
edgeTo[to] = edge;
if(indexMinPriorityxQueue.contains(to)){
indexMinPriorityxQueue.changeItem(to, distTo(to));
}else{
indexMinPriorityxQueue.insert(to, distTo(to));
}
}
}
}
/**
* 获得顶点s到v最短路径的总权重
* @param v
* @return
*/
public double distTo(int v){
return distTo[v];
}
public boolean hasPath(int v){
return distTo[v] < Double.POSITIVE_INFINITY;
}
public Queue<DirectEdge> edges(int v){
Queue<DirectEdge> directEdges = new Queue<>();
if(!this.hasPath(v)){
return null;
}
while (true){
DirectEdge edge = this.edgeTo[v];
if(edge == null){
break;
}
directEdges.enqueue(edge);
int from = edge.getFrom();
v = from;
}
return directEdges;
}
}