写在前面:
我也是一名java语言的爱好者,仅以此文作为学习的记录,对于文中出现的代码规范,代码格式,算法效率等问题,希望各路大神不吝赐教,在下感激不尽。同是学习的同学也同样希望互相交流,取长补短。
——zsferrier@126.com
Dijkstra算法是贪心算法最好的例子,贪婪算法一般分阶段求解一个问题,在每个阶段它都把出现的当作最好的去处理。
首先给出数据类型
//节点所存储的数据域
class Vertex{
public List<Integer> adjacency;//邻接表
public boolean known; //标记
public int dist; //距离出发点的距离
public Vertex path;//路径
public int vname;//节点编号
public Vertex(){
known = false;
dist = MaxLen;
path = null;
}
}
邻接表存储与该节点邻接所有节点的边信息,不直接相邻的节点距离为MaxLen(预定义,MaxLen=1000表示不距离不可达)
known标记节点是否已知。
dist为此节点当前距离原点的距离MaxLen表示不可达。
path记录路径上的上一个节点。
vname为节点编号。
dijkstra分阶段求解,在每个阶段,选择一个节点v,它在所有的unknown节点中具有最小的dist值,纳入已知节点。根据该节点的邻接域(边的值cvw)来计算其他unknown状态下的邻接点w的dist,与Vw的原dist值比较,若v.dist+cvw<w.dist,则更新。
赋权图
下面给出Dijsktra算法伪代码:
void dijkstra( Vertex s )
{
for each Vertex v
{
v.dist = INFINITY;
v.known = false;
}
s.dist = 0;
while( there is an unknown distance vertex )
{
Vertex v = smallest unknown distance vertex;
v.known = true;
for each Vertex w adjacent to v if( !w.known )
{
DistType cvw = cost of edge from v to w;
if( v.dist + cvw < w.dist )
{
// Update w
decrease( w.dist to v.dist + cvw ); w.path = v;
}
}
}
}
JAVA语言实现:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
/**
* @param args
*/
//节点所存储的数据域
class Vertex{
public List<Integer> adjacency;//邻接表
public boolean known; //标记
public int dist; //距离出发点的距离
public Vertex path;//路径
public int vname;//节点编号
public Vertex(){
known = false;
dist = MaxLen;
path = null;
}
}
private static int MaxLen = 1000;//表示不可达
//有权图,使用邻接表来表示图。
private static Vertex[] verArray = new Vertex[7];
//这个函数用来判断还有没有unknown distance vertex
public static boolean judge(){
for (Vertex v : verArray) {
if(v.known==false){
return true;
}
}
return false;
}
//这个函数用来返回再unknown中最小的distance vertex
public static Vertex smallestVertex(){
int num = 0;
int value = MaxLen;
for (int i = 0; i < verArray.length; i++) {
if((verArray[i].known==false)&&(verArray[i].dist<value)){
num = i;
value = verArray[i].dist;
}
}
return verArray[num];
}
public static void dijkstra(int s){
verArray[s].dist = 0;//起点的dist为零
while(judge()){
Vertex vtex = smallestVertex();
vtex.known = true;
for (Integer i : vtex.adjacency) {
if(!verArray[vtex.adjacency.indexOf(i)].known){
if (vtex.dist+i<verArray[vtex.adjacency.indexOf(i)].dist) {
//Update
verArray[vtex.adjacency.indexOf(i)].dist = vtex.dist+i;
verArray[vtex.adjacency.indexOf(i)].path = vtex;
}
}
}
}
}
//输出路径函数
public static void printGraph(Vertex v){
if(v.path!=null){
printGraph(v.path);
}
System.out.print("V"+v.vname+" ");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//初始化
verArray[0] = new Main().new Vertex();
verArray[1] = new Main().new Vertex();
verArray[2] = new Main().new Vertex();
verArray[3] = new Main().new Vertex();
verArray[4] = new Main().new Vertex();
verArray[5] = new Main().new Vertex();
verArray[6] = new Main().new Vertex();
verArray[0].adjacency = new ArrayList<Integer>(Arrays.asList(0,2,MaxLen,1,MaxLen,MaxLen,MaxLen));
verArray[0].vname = 0;
verArray[1].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,0,MaxLen,3,10,MaxLen,MaxLen));
verArray[1].vname = 1;
verArray[2].adjacency = new ArrayList<Integer>(Arrays.asList(4,MaxLen,0,MaxLen,MaxLen,5,MaxLen));
verArray[2].vname = 2;
verArray[3].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,2,0,2,8,4));
verArray[3].vname = 3;
verArray[4].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,MaxLen,MaxLen,0,MaxLen,6));
verArray[4].vname = 4;
verArray[5].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,MaxLen,MaxLen,MaxLen,0,MaxLen));
verArray[5].vname = 5;
verArray[6].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,MaxLen,MaxLen,MaxLen,1,0));
verArray[6].vname = 6;
//起点从v0开始
dijkstra(0);
for (Vertex v : verArray) {
System.out.print("到节点V"+v.vname+"的最短路径为: ");
printGraph(v);
System.out.println();
}
}
}
控制台输出
这里注意一点,我定义的Vertex是个内部类,在主函数中如果直接使用new动态申请内存的时候会出现这样的错误。
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
No enclosing instance of type Main is accessible. Must qualify the allocation with an enclosing instance of type Main (e.g. x.new A() where x is an instance of Main).
at DijkstraAlg.Main.main(Main.java:75)
报错位置为
verArray[0] = new Vertex();
这是由于Java中的内部类没有使用static修饰,其构造函数被认为是一个动态方法,而主函数main为静态函数,不能直接调用,解决的方法为在new Vertex前加上外部类,即:
verArray[0] = new Main().new Vertex();
转载请标明出处,谢谢 by zsferrier@126.com