Java版邻接表

要写一个Java版的邻接表,发现连概念都忘了。重新理解了下邻接表写了代码作为备忘:

邻接表概念(摘自:http://blog.csdn.net/jnu_simba/article/details/8866844

对于图来说,邻接矩阵是不错的一种图存储结构,但是我们也发现,对于边数相对顶点较少的图,这种结构是存在对存储空间的极大浪费的。因此我们考虑另外一种存储结构方式:邻接表(Adjacency List),即数组与链表相结合的存储方法。

邻接表的处理方法是这样的。

1、图中顶点用一个一维数组存储,另外,对于顶点数组中,每个数据元素还需要存储指向第一个邻接点的指针,以便于查找该顶点的边信息。

2、图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以用单链表存储,无向图称为顶点vi的边表,有向图称为顶点vi作为弧尾的出边表。


Dijkstra算法

1.定义概览

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。

问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)

2.算法描述

1)算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

2)算法步骤:

a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。

b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。

d.重复步骤b和c直到所有顶点都包含在S中。

执行动画过程如下图


代码

package cn.Adjacency;
import java.util.*;

public class Vertex implements Comparable<Vertex>{
	
	public final String name;
	public ArrayList<Edge> neighbours;
	public LinkedList<Vertex> path;
	public double minDistance = Double.POSITIVE_INFINITY;
	public Vertex previous;
	
	public int compareTo(Vertex other){
		return Double.compare(minDistance,other.minDistance);		
	}
	
	public Vertex(String name){
		this.name = name;
		neighbours = new ArrayList<Edge>();
		path = new LinkedList<Vertex>();
	}
	
	public String toString(){
		return name;
	}
	
	public double getMinDistance() {
		return minDistance;
	}
	public void setMinDistance(double minDistance) {
		this.minDistance = minDistance;
	}
	
}

package cn.Adjacency;
//To represent the edges in the graph.
public class Edge{
  public final Vertex target;
	public final double weight;
	public Edge(Vertex target, double weight){
		this.target = target;
		this.weight = weight;
	}
}

package cn.Adjacency;

import java.util.LinkedHashMap;
import java.util.Map;

public class Graph {
  private Map<String, Vertex> vertices;
	public Graph(String[] vertexNames){
		vertices = new LinkedHashMap<String, Vertex>();
		for(String name : vertexNames){
			vertices.put(name, new Vertex(name));
		}
	}
	
	public void addEdge(String srcName, String destName, int weight){
		Vertex s = vertices.get(srcName);
		Edge new_edge = new Edge(vertices.get(destName),weight);
		s.neighbours.add(new_edge);
	}
	
	/**
	 * <p>
	 * 删除边, 取得两个顶点即可:
	 * 查找原顶点对应的邻接表的边,边的另一端等于目标顶点就是要删除的边
	 * <p>
	 * 
	 * @param src 原顶点
	 * @param dest 目标顶点
	 * @return
	 */
	public Edge delEdge(String src, String dest){
		Vertex s = vertices.get(src);
		Vertex d = vertices.get(dest);
		
		Edge delEdge = null;
		for(Edge edge : s.neighbours){
			if(edge.target == d){
				delEdge = edge;
			}
		}
		s.neighbours.remove(delEdge);
		
		return delEdge;
	}
	
	/**
	 *  <p>
	 *  默认最短路径充值,图被算一次选择一个顶点算了一次最短路径后会
	 *  更改最短路径值,要算其他顶点开始的最短路径得重新设置每个顶点最短
	 *  路径的初始值
	 *  <p>
	 */
	public void resetMinDistance(){
		for (String key : vertices.keySet()) {
			Vertex v = vertices.get(key);
			v.setMinDistance(Double.POSITIVE_INFINITY);
		}
	}
	
	public Map<String,Vertex> getVertices() {
		return vertices;
	}
	
	public Vertex getVertex(String vertName){
		return vertices.get(vertName);
	}
}

package cn.Adjacency;

import java.util.LinkedList;
import java.util.PriorityQueue;

/**
 * <p>
 * 最短路径算法
 * <p>
 * @author 天行健
 *
 */
public class Dijkstra{

  public static void main(String[] arg){
		
		Dijkstra obj = new Dijkstra();
		
		// Create a new graph.
		Graph g = new Graph(new String[]{"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"});
		
		// Add the required edges.
		g.addEdge("v0", "v1", 4); g.addEdge("v0", "v7", 8);
		g.addEdge("v1", "v2", 8); g.addEdge("v1", "v7", 11); g.addEdge("v2", "v1", 8);
		g.addEdge("v2", "v8", 2); g.addEdge("v2", "v5", 4); g.addEdge("v2", "v3", 7);
		g.addEdge("v3", "v2", 7); g.addEdge("v3", "v5", 14); g.addEdge("v3", "v4", 9); 
		g.addEdge("v4", "v3", 9); g.addEdge("v4", "v5", 10); 
		g.addEdge("v5", "v4", 10); g.addEdge("v5", "v3", 9); g.addEdge("v5", "v2", 4); g.addEdge("v5", "v6", 2);
		g.addEdge("v6", "v7", 1); g.addEdge("v6", "v8", 6); g.addEdge("v6", "v5", 2);
		g.addEdge("v7", "v0", 8); g.addEdge("v7", "v8", 7); g.addEdge("v7", "v1", 11); g.addEdge("v7", "v6", 1);
		g.addEdge("v8", "v2", 2); g.addEdge("v8", "v7", 7); g.addEdge("v8", "v6", 6);
		
	
		// Calculate Dijkstra.
		obj.calculate(g.getVertex("v0"));	

		// Print the minimum Distance.
		for(Vertex v : g.getVertices().values()){
			System.out.print("Vertex - "+v+" , Dist - "+ v.minDistance+" , Path - ");
			for(Vertex pathvert:v.path) {
				System.out.print(pathvert+" ");
			}
			System.out.println(""+v);
		}

		System.out.println("---------**********------------");
		Edge delEdge = g.delEdge("v0", "v7");
		System.out.println("被删除的边(已字符为顶点主键):" + delEdge);
		g.resetMinDistance();
		obj.calculate(g.getVertex("v0"));
		// 删除一条边后的最短路径
		for(Vertex v : g.getVertices().values()){
			System.out.print("Vertex - " + v + " , Dist - " + v.minDistance
					+ " , Path - ");
			for (Vertex pathvert : v.path) {
				System.out.print(pathvert + " ");
			}
			System.out.println("" + v);
		}
	}

	public void calculate(Vertex source){
		// Algo:
		// 1. Take the unvisited node with minimum weight.
		// 2. Visit all its neighbours.
		// 3. Update the distances for all the neighbours (In the Priority Queue).
		// Repeat the process till all the connected nodes are visited.
		
		source.minDistance = 0;
		PriorityQueue<Vertex> queue = new PriorityQueue<Vertex>();
		queue.add(source);
		
		while(!queue.isEmpty()){
			
			Vertex u = queue.poll();
		
			for(Edge neighbour:u.neighbours){
				Double newDist = u.minDistance+neighbour.weight;
				
				if(neighbour.target.minDistance>newDist){
					// Remove the node from the queue to update the distance value.
					queue.remove(neighbour.target);
					neighbour.target.minDistance = newDist;
					
					// Take the path visited till now and add the new node.s
					neighbour.target.path = new LinkedList<Vertex>(u.path);
					neighbour.target.path.add(u);
					
					//Reenter the node with new distance.
					queue.add(neighbour.target);					
				}
			}
		}
	}

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值