`
shenyu
  • 浏览: 122951 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

图-最小路径

阅读更多

这里使用的是Dijkstra来计算最短路径。事实上Dijkstra完成时,指定节点到所有节点的最小路径均已求出。

算法简述如下:

准备好两个辅助性数据结构:

1 ParentLength : 用来记录到当前节点之前的父节点,与到当前节点的最小路径

2 Path: 记录指定节点到所有节点的ParentLength。初始化时,所有的ParentLength的父节点都为指定的起始节点,长度都是INFINITY,代表没有联通,距离无穷大。

Path的关键算法是adjust(from,to,length),每当发现一条新的,从一个已访问的节点(from)到未访问的节点(to)之间的新路径时,Path则用其更新ParentLength列表,重新计算到那个未访问节点(to)的最新距离:以前到from节点的距离+新的距离,然后比较它与to节点对应的ParentLength老的距离之间的长度,如果新距离短,则将to节点对应的ParentLength更新为长度为新距离的,父节点为from;以此步骤保证Path总是保持当前遍历状态下,到各个节点的最短路径。

Path的另一个关键算法是getMin,它会返回到所有未访问节点中,最短的路径的那个节点。

图使用邻接矩阵法表示,关于邻接矩阵可参见:Graph 图-邻接表法

Graph.path是最小路径算法,工作方式如下:

    根据指定的起始节点初始化返回值Path对象。

将指定的起始节点标志为已访问。并设置为当前节点。

然后

1 找到当前节点所有联通的未知节点,和到这些路径长度,调用Path.adjust更新Path。

2 步骤 1 结束后,从调用Path.getMin获得到所有未访问节点中,最短的路径的那个节点。标志为访问过,并作为当前节点。

3 重复 步骤 1 步骤 2 n次(n为图中的节点数量),算法结束。

代码中的Path.print()为打印函数,为测试之用。

Path.main()提供简单测试。

 

class ParentLength {	//记载上一个节点与当前最小路径
	private int parent;		//上一个节点
	private int length;		//最小路径长度
	ParentLength(int parent, int length) {
		this.parent = parent;
		this.length = length;
	}

	int parent() {	return parent; }
	int length() {	return length; }
}

class Path {	//存储最小路径
	private ParentLength[] pls;
	private Graph g;	//确定指定位置的节点是否被访问过和打印时使用
	Path(int size, int start, Graph g) { 
		//初始化最小路径数组,将所有最小路径的起点都置为start,并将路径长度置为INFINITY
		pls = new ParentLength[size];	
		for(int i=0; i<size; i++) 
			pls[i] = new ParentLength(start,Graph.INFINITY);
		this.g = g;
	}
	
	//根据新发现的路径调整最小路径
	void adjust(int from, int to, int length) {
		//根据上一个节点的路径,计算出新的路径长度
		int newLength = pls[from].length() != Graph.INFINITY? 
			pls[from].length() + length: length;
		//如果到指定节点的新路径长度小于原来的最小路径,则更新到该节点的最小路径,和其父节点
		if(newLength < pls[to].length()) pls[to] = new ParentLength(from,newLength);
	}

	int getMin() {	//求得到当前所有未访问节点的最近的一个节点
		int pos = 0;
		for(int i=1; i<pls.length; i++)
			if(!g.isVisited(i) && pls[i].length() < pls[pos].length()) pos = i;
		return pos;
	}

	void print() {	//打印
		for(int i=0; i<pls.length; i++) {
			int current = i;	
			System.out.print((pls[current].length() == Graph.INFINITY? "INFINITY": pls[current].length()) + "  " );
			do {
				System.out.print(g.get(current) + " <-- ");
				current = pls[current].parent();	
			} while(current != pls[current].parent());
			System.out.println(g.get(current));
		}
	}
}

class Vertex { //顶点,记载数据value,并记载是否访问过
	private Object value;
	private boolean isVisited;
	Vertex(Object value) {
		this.value = value;
	}

	void visit() { isVisited = true; }
	void clean() {	isVisited = false; }
	boolean isVisited() { return isVisited; }
	Object value() { return value; }
	@Override public String toString() {	return "" + value; }
}

class Graph {
	private Vertex[] vertexs;
	private int[][] adjMat;
	private int length = 0;
	static final int INFINITY = ~(1<<31);	//整数的最大值,表示没有路径

	Graph(int size) {	//初始化
		vertexs = new Vertex[size];
		adjMat = new int[size][size];
		for(int i=0; i<size; i++)	//将邻接矩阵初始化为全部不通
			for(int j=0; j<size; j++)
				adjMat[i][j] = INFINITY;
	}

	void add(Object value) {	//添加顶点
		assert length <= vertexs.length;
		vertexs[length++] = new Vertex(value);
	}

	void connect(int from, int to, int length) {
		adjMat[from][to] = length;	//设置指定节点之间的有向路径
	}

	/**
	 * 在邻接矩阵中,查找指定顶点的未访问过邻居顶点
	 * 如果从从起点到终点的边存在,且没有标志为访问,则返回终点下标。
	 * @param offset 指定开始查找的列
	 * @param index	指定查找的行
	 */
	int findNeighbor(int index,int offset) {
		for(int i=offset; i<length; i++) {
			if(adjMat[index][i] != INFINITY && !vertexs[i].isVisited()) return i;
		}
		return -1;
	}

	Vertex get(int index) {	return vertexs[index];	}

	Path path(int index) {	//最小路径算法
		assert vertexs[index] != null;
		Path result = new Path(length,index,this); //初始化Path
		vertexs[index].visit();	//将其实节点标志为访问过
		for(int n=1; n<length; n++) {	//一共经过n此迭代就可得到最终结果
			int i = 0;
			while((i = findNeighbor(index,i+1)) != -1)	//寻找当前节点的所有为访问邻居
				result.adjust(index, i, adjMat[index][i]);	//根据新路线调整最小路径
			index = result.getMin();	//将当前节点更新为路径表中为访问的最近的那个节点
			vertexs[index].visit();	//将当前节点标志为访问过;
		}
		clean();
		return result;
	}

	boolean isVisited(int index) { return vertexs[index].isVisited(); }

	void clean() { for(Vertex v: vertexs) if(v != null)v.clean(); }

	public static void main(String[] args) {
		Graph g = new Graph(20);
		//添加节点
		g.add('a');
		g.add('b');
		g.add('c');
		g.add('d');
		g.add('e');
		//添加有向有权边
		g.connect(0,1,50);
		g.connect(0,3,80);
		g.connect(1,2,60);
		g.connect(1,3,90);
		g.connect(2,4,40);
		g.connect(3,2,20);
		g.connect(3,4,70);
		g.connect(4,1,50);
		Path p = g.path(0);	//获得最小路径
		p.print();	//打印
	}
}
 
评论
3 楼 run_xiao 2008-08-06  
A* 算法??没听说啊,大多数教科书上都还是Dijkstra吧
2 楼 kldwq2002 2008-07-28  
Great job!

This blog is the best one in javaeye, keep update please.
1 楼 feng_gladys 2008-05-29  
获取最小路径的算法基本都是A* 算法的变体,Dijkstra算法很少用吧

相关推荐

    贪心算法-最小平铺路径

    贪心算法-最小平铺路径,简单讲解贪心算法。贪心算法、算法导论、算法、c语言。 贪心算法-最小平铺路径,简单讲解贪心算法。贪心算法、算法导论、算法、c语言。

    数据结构-图-最小生成树-最短路径

    最短路径问题的目标是在图中找到两个顶点之间的最短路径,即权重之和最小的路径。Dijkstra算法是求解单源最短路径的经典算法,它适用于边权重非负的图,通过贪心策略来实现,能有效地求出从起点到其他各点的最短路径...

    图论网络分析-最小费用最大流算法程序-最短路径算法

    本主题聚焦于两个核心算法:最小费用最大流算法和最短路径算法,这两者都是在图的背景下进行优化的重要工具。 最小费用最大流算法(Minimum-Cost Maximum-Flow Algorithm)是图论中的一个关键概念,用于在有向加权...

    网络最大流-最小割问题

    此类问题的核心在于寻找图中源点(S)到汇点(T)之间的最大数据流(或称为“流”)值以及与之相对应的最小割。这些概念不仅在理论计算机科学中有着重要地位,在实际应用中也极为常见,例如在网络流量控制、物流配送...

    databinQ#garnetbook#64-最小路径和1

    题目描述64. 最小路径和给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。解题思路走到i, j点, 只可

    图算法演示系统----最小生成树,最短路径,拓扑排序,关键路径

    在给定的“图算法演示系统”中,我们可以看到几个核心概念:最小生成树、最短路径、拓扑排序以及关键路径。这些都是图论中的基础算法,广泛应用于网络设计、任务调度、资源分配等领域。 1. 最小生成树(Minimum ...

    图-最短路径-可视化.zip

    在图中,最短路径通常是指从起点到终点经过的边的权重之和最小的路径。这里的权重可以理解为距离、时间或其他成本。解决这个问题,我们可以采用几种经典算法: 1. **Dijkstra算法**:Dijkstra算法是最常用的求解...

    MATLAB工具箱大全-dijkstra最小成本路径算法

    这个MATLAB工具箱提供了实现Dijkstra算法的完整功能,帮助用户高效地计算网络或图中的最小成本路径。下面将详细介绍Dijkstra算法以及其在MATLAB中的应用。 Dijkstra算法是由荷兰计算机科学家艾兹格·迪科斯彻...

    最短路径算法实现 k-shortest-paths

    最短路径算法是图论中的一个经典问题,用于寻找网络中的两点之间具有最小成本或最短距离的路径。在计算机科学、交通规划、通信网络等领域都有广泛应用。k-Shortest Paths(k-最短路径)则是在这个基础上进一步扩展,...

    论文研究-最小时间路径算法的改进及在路径优化中的应用.pdf

    由于城市交通网络中路径行程时间是随着时间的变化而变化的,求解最小时间路径比较困难,为此提出把交通网络抽象为时间依赖的网络模型的解决方法。对时间依赖网络模型和理论基础进行分析,指出文献[1]描述的最小...

    分配最优-路径选择-运输-运输路径选择.zip

    每次迭代中,算法会尝试找到一条从源到汇的路径,该路径上的反向边都不满容量,且这条路径的费用增量最小。一旦找不到这样的路径,就说明达到了最大流状态,此时的流就是最优解。 在实际应用中,这个算法可以被物流...

    最短路经-关键路径的实现

    最短路径问题是在图论中一个重要的概念,指的是在一个加权图中寻找两点间路径,使得路径上所有边的权重之和最小。这类问题在很多实际场景中都有应用,比如在计算机网络中寻找数据包传输的最佳路径,在地图导航系统中...

    图算法-最小生成树和单源顶点最短路径

    本主题聚焦于两个核心的图算法:最小生成树(Minimum Spanning Tree, MST)和单源顶点最短路径(Single Source Shortest Path, SSSP)。接下来,我们将深入探讨这两个概念以及如何通过编程实现它们。 最小生成树...

    C语言求最小路径问题

    在计算机科学中,最小路径问题通常涉及到找到网络或图中两个节点之间最短的路径。这个问题在各种领域都有应用,例如路由选择、交通规划、电路设计等。在本例中,我们将探讨如何使用C语言来解决这个问题,主要涉及两...

    数据结构作业-最小生成树,最短路径,所有路径,景点信息展示

    **最短路径(Shortest Path)** 指的是在图中找到从一个源节点到另一个目标节点的路径,使得经过的所有边的权重之和最小。Dijkstra算法是最常用的方法,适用于没有负权边的图。对于有权负边的情况,可以使用Bellman-...

    偏最小二乘路径建模 (PLS-PM)算法 的Python 3 实现

    plspm是一个 Python 3 包,专门用于偏最小二乘路径建模 (PLS-PM) 分析。它是 R 包 plspm 的一个端口,具有从 R 包 seminr采用的附加功能 PLSPM(偏最小二乘路径建模)是一种基于相关性的结构方程建模 (SEM) 算法。它...

    Union-find压缩路径最小生成树

    利用Union-find算法实现路径压缩最小生成树,使用c编写

    公园地图问题-最小生成树-MFC

    最小生成树是一种特殊的树形结构,它是无向图的一个子集,包含了图中所有的顶点,并且没有环路,且边的权重之和尽可能小。解决这个问题有多种算法,如Kruskal's算法和Prim's算法,它们都能有效地找到最小生成树。 ...

    多段图的最小路径求解c++实现

    用动态规划实现求解多段图的最小路径,该代码分别实现从前和从后搜索

    求最短路径 -最短路径 - Short path

    在计算机科学领域,最短路径问题是一个经典的图论问题,主要关注如何在图中的节点之间找到具有最小权重的路径。这个问题在很多应用中都非常重要,比如网络路由、交通规划、社交网络分析等。"Short path" 或 "最短...

Global site tag (gtag.js) - Google Analytics