有向图的无权图最短路径算法与带权图的Dijkstra算法

  最短路径算法是图论中的常见问题,在实际中有着较为广泛的应用,比如查找从一个地方到另一个地方的最快方式。问题可以概括为,对于某个输入顶点s,给出s到所有其它顶点的最短路径。水平有限,暂时先对这个问题的求解做简单记录。

  无权图是有权最短路径的特例,即边的权重均是1。算法类似于BFS(宽度优先搜索),在实现时需要一个宽度优先搜索的队列。全局变量Distance用来保存所有点到输入顶点的距离。以邻接表表示图,无权图最短路径算法:

//无权图的最短路径算法
	static void UnweightedShortestPath(Graph g, int start){
		Queue<Integer> Q = new LinkedList<Integer>();
		int v,w;
		Q.offer(start);
		g.getVertics().get(start).setVivited(true);  //输入顶点被标记为已访问
		for(int i=0;i<g.getVertexCount();i++)
			Distance[i] = -1;   //初始化Distance,都为-1
		Distance[start] = 0;
		while(!Q.isEmpty()){
			v = Q.remove();    //v是队首的整数,记录了图中顶点的序号
			while(g.getAdjUnvisitedVertex(v)!=-1){           //寻找顶点v指向的所有的点
				w = g.getAdjUnvisitedVertex(v);
				g.getVertics().get(w).setVivited(true);  //图的对应部分标记为已访问,每个顶点只能被访问一次
				if(Distance[w] == -1){
					Distance[w] = Distance[v]+1;
					Path[w] = v;
					Q.offer(w);
				}
			}//while
		}//while
	}
  Dijkstra算法是解决最短路径问题的常见算法,过程需要使用优先队列来代替无权图最短路径算法。源点到某个顶点的距离为从源点到该顶点的路径上的所有边权值之和,当新计算得到的距离小于原有的距离时,更新距离。

//Dijkstra算法
	static void Dijkstra(Graph g, int start){
		MinHeap PQ = new MinHeap(10, 0);     //最小堆实现优先队列
		int v,w;
		PQ.Insert(new NodeWithProority(0,0));//NodeWithprority是一个只包括顶点的序号和权值(到给定起始点的距离)的类
		g.getVertics().get(start).setVivited(true);
		for( int i=0;i<g.getVertexCount();i++ )
			Distance[i]=-1;
		Distance[start] = 0;
		while(!PQ.isEmpty()){
			v = PQ.DeleteMin().node;
			while(g.getAdjUnvisitedVertex(v)!=-1){
				w = g.getAdjUnvisitedVertex(v);
				g.getVertics().get(w).setVivited(true);  //图的对应部分标记为已访问,每个顶点只能被访问一次
				int d = Distance[v]+g.Weight(v, w);      //计算新的距离
				if(Distance[w] == -1){
					Distance[w] = d;
					PQ.Insert(new NodeWithProority(w, d));
					Path[w] = v;
				}//if
				if(Distance[w] > d){                    //如果新的距离比原有的小,需要更新距离
					Distance[w] = d;
					for(int i=0;i<PQ.count;i++){
						if(PQ.array[i].node == w){
							PQ.array[i].priority = d;
							PQ.Parent(0);
						}
					}
					Path[w] = v;
				}//if
			}//while
			for(int j=0;j<g.getVertexCount();j++)  //将访问标记初始化
				g.getVertics().get(j).setVivited(false);
		}//while
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值