【JAVA算法】图论算法 -- Dijkstra算法

写在前面:

    我也是一名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,则更新。

赋权图

《【JAVA算法】图论算法 -- Dijkstra算法》

下面给出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();
		}
	}
}

控制台输出

《【JAVA算法】图论算法 -- Dijkstra算法》

这里注意一点,我定义的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

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/qq_37935670/article/details/79708409
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞