`

用邻接表实现图的深度优先遍历、广度优先遍历、最短路径(无权图)

 
阅读更多
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class Graph {


	/**关键字:图 邻接表 深度优先遍历 广度优先遍历 最短路径
	 * key words:Graph Adjacent-list depthFirstVisit breadthFirstVisit getCheapestPath
	 * 1.Graph is a collection of Vertex and Edge.
	 * When you want to implement 'Graph',you deal with two missions:how to implement 'Vertex' and 'Edge'
	 *  a.Vertex:
	 *    Type label-->Vertex's ID,to separate one Vertex from another,like 'A','B',or 0,1,2
	 *    List<Edge> edgeList-->store edges that start with this Vertex.
	 *    ...<output omit>
	 *  b.Edge(as Inner class of Vertex):
	 *    endVertex-->(begin,end),the outer class is 'begin',endVertex is 'end'
	 *    ...<output omit>
	 * 2.In the following,we 
	 *  a.use ArrayList to store Vertices
	 *  b.use 'char' as Vertex's ID
	*/
	private List<Vertex> vertices;
	private int edgeCount;
	private List<Vertex> depthFirstResult;
	private List<Vertex> breadthFirstResult;
	
public void breadthFirstVisit(char beginLabel){
		
		Vertex origin=this.getVertexByChar(beginLabel);
		if(origin==null)return;
		List<Vertex> queue=new LinkedList<Vertex>();
		origin.setVisited(true);
		queue.add(origin);
		breadthFirstResult.add(origin);
		Vertex curVertex=null;
		while(!queue.isEmpty()){
			curVertex=queue.remove(0);
			while(curVertex.getFirstUnvisitedNeighbor()!=null){
				Vertex tmpVertex=curVertex.getFirstUnvisitedNeighbor();
				tmpVertex.setVisited(true);
				queue.add(tmpVertex);
				breadthFirstResult.add(tmpVertex);
			}
			
		}
		printVertexList(breadthFirstResult);
}
	
	public void depthFirstVisit(char beginLabel){
		
		Vertex origin=this.getVertexByChar(beginLabel);
		if(origin==null)return;
		Stack<Vertex> stack=new Stack<Vertex>();
		origin.setVisited(true);
		stack.push(origin);
		depthFirstResult.add(origin);
		Vertex curVertex=null;
		while(!stack.isEmpty()){
			curVertex=stack.peek();
			Vertex tmpVertex=curVertex.getFirstUnvisitedNeighbor();
			if(tmpVertex!=null){
				tmpVertex.setVisited(true);
				depthFirstResult.add(tmpVertex);
				stack.push(tmpVertex);
			}else{
				stack.pop();
			}
		}
		printVertexList(depthFirstResult);
	}
	
	//getShortestPath.Base on breadthFirstVisit.the edge has no weight.
	public double getShortestPath(char beginLabel,char endLabel,Stack<Vertex> stack){
		resetVertices();
		Vertex begin=this.getVertexByChar(beginLabel);
		Vertex end=this.getVertexByChar(endLabel);
		begin.setVisited(true);
		List<Vertex> queue=new LinkedList<Vertex>();
		queue.add(begin);
		boolean done=false;
		while(!done&&!queue.isEmpty()){
			Vertex curVertex=queue.remove(0);
			while(!done&&curVertex.getFirstUnvisitedNeighbor()!=null){
				Vertex tmpVertex=curVertex.getFirstUnvisitedNeighbor();
				tmpVertex.setVisited(true);
				double	tmpCost=curVertex.getCost()+1;
				tmpVertex.setPreviousVertex(curVertex);
				tmpVertex.setCost(tmpCost);
				queue.add(tmpVertex);
				if(tmpVertex.equals(end)){
					done=true;
				}
			}
		}
		double pathLength=end.getCost();
		//find the path.traverse back from end
		while(end!=null){
			stack.push(end);
			end=end.getPreviousVertex();
		}
		return pathLength;
	}
	
	public boolean addEdge(char beginLabel,char endLabel,double weight){
		int beginIndex=vertices.indexOf(new Vertex(beginLabel));
		int endIndex=vertices.indexOf(new Vertex(endLabel));
		Vertex beginVertex=vertices.get(beginIndex);
		Vertex endVertex=vertices.get(endIndex);
		boolean result=beginVertex.connect(endVertex,weight);
		edgeCount++;
		return result;
	}
	public boolean addEdge(char beginLabel,char endLabel){
		return addEdge(beginLabel,endLabel,0);
	}
	public boolean addVertex(char label){
		boolean result=false;
		Vertex newVertex=new Vertex(label);
		if(!vertices.contains(newVertex)){
			vertices.add(newVertex);//reject duplicate vertex
			result=true;
		}
		return result;
	}
	public void printVertexList(List<Vertex> list){
		for(int i=0,len=list.size();i<len;i++){
			Vertex vertex=list.get(i);
			System.out.print(vertex.getLabel()+" ");
		}
		System.out.println();
	}
	
	public void resetVertices(){
		for(int i=0,len=vertices.size();i<len;i++){
			Vertex vertex=vertices.get(i);
			vertex.setPreviousVertex(null);
			vertex.setVisited(false);
			vertex.setCost(0);
		}
	}
	
	public Vertex getVertexByChar(char target){
		Vertex vertex=null;
		for(int i=0,len=vertices.size();i<len;i++){
			vertex=vertices.get(i);
			Character xx=vertex.getLabel();
			if(xx.charValue()==target){
				return vertex;
			}
		}
		return vertex;
	}
	
	public Graph(){
		vertices=new ArrayList<Vertex>();
		edgeCount=0;
		depthFirstResult=new ArrayList<Vertex>();
		breadthFirstResult=new ArrayList<Vertex>();
	}

	
	
	public static void main(String[] args) {
		
		Graph graph=createGapth();
		graph.depthFirstVisit('7');//depthFirstVisit,start with '7'
		graph.resetVertices();
		graph.breadthFirstVisit('0');//breadthFirstVisit,start with '0'
		
		//shortest path
		Stack<Vertex> pathStack=new Stack<Vertex>();
		//from '0' to '7'.
		double pathLength=graph.getShortestPath('0','7',pathStack);
		System.out.println(pathLength);
		while(!pathStack.isEmpty()){
			Vertex vertex=pathStack.pop();
			System.out.print(vertex.getLabel()+" ");
		}
		
		//BasicGraphInterface<String> airMap=new UndirectedGraph<String>();
		//airMap.
		
	}
	
	public static Graph createGapth(){
		/*
		 0----1---2
		 | \  |	  |
		 |  \ |   |
		 |   \|   |
		 3	  4	  5
		 |	 /
		 |  /
		 | /
		 6---7
		 the adjacent List is :
		 0-->4--3--1
		 1-->4--2--0
		 2-->5--1
		 3-->6--0
		 4-->6--1--0
		 5-->2
		 6-->7--4--3
		 7-->6
		 */
		
		Graph graph=new Graph();
		graph.addVertex('0');
		graph.addVertex('1');
		graph.addVertex('2');
		graph.addVertex('3');
		graph.addVertex('4');
		graph.addVertex('5');
		graph.addVertex('6');
		graph.addVertex('7');
		
		graph.addEdge('0','4');
		graph.addEdge('0','3');
		graph.addEdge('0','1');
		
		graph.addEdge('1','4');
		graph.addEdge('1','2');
		graph.addEdge('1','0');
		
		graph.addEdge('2','5');
		graph.addEdge('2','1');
		
		graph.addEdge('3','6');
		graph.addEdge('3','0');
		
		graph.addEdge('4','6');
		graph.addEdge('4','1');
		graph.addEdge('4','0');
		
		graph.addEdge('5','2');
		
		graph.addEdge('6','7');
		graph.addEdge('6','4');
		graph.addEdge('6','3');
		
		graph.addEdge('7','6');
		
		return graph;
	}
}


class Vertex{
	private char label;
	private List<Edge> edgeList;
	private boolean isVisited;
	private Vertex previousVertex;//use it in the method-'getShortestPath()'
	private double cost;//the cost from beginning to this vertex 
	
	public Vertex(char label){
		this.label=label;
		edgeList=new ArrayList<Edge>();
		isVisited=false;
		previousVertex=null;
		cost=0;
	}
	public boolean isVisited(){
		return isVisited;
	}
	public void visit(){
		System.out.println(this.label);
		this.isVisited=true;
	}
	
	public void setPreviousVertex(Vertex vertex){
		this.previousVertex=vertex;
	}
	public void setVisited(Boolean isVisited){
		this.isVisited=isVisited;
	}
	public void setCost(double cost){
		this.cost=cost;
	}
	public Vertex getFirstNeighbor(){
		Vertex neighbor=this.edgeList.get(0).endVertex;
		return neighbor;
	}
	public char getLabel(){
		return this.label;
	}
	
	public double getCost(){
		return this.cost;
	}
	public Vertex getPreviousVertex(){
		return this.previousVertex;
	}
	public Vertex getFirstUnvisitedNeighbor(){
		Vertex unVisitedNeighbor=null;
		for(int i=0,len=edgeList.size();i<len;i++){
			Vertex vertex=edgeList.get(i).endVertex;
			if(!vertex.isVisited){
				unVisitedNeighbor=vertex;
				break;
			}
		}
		return unVisitedNeighbor;
	}
	public boolean equals(Object object){
		boolean result=false;
		if(this==object)return true;
		if(object instanceof Vertex){
			Vertex otherVertex=(Vertex)object;
			result=this.label==otherVertex.label;
		}
		return result;
	}
	public boolean connect(Vertex endVertex,double weight){
		
		boolean result=false;//result=true if successful
		
		if(!this.equals(endVertex)){//connections should occur in different Vertices
			boolean isDuplicateEdge=false;
			List<Edge> edgeList=this.edgeList;
			if(edgeList.contains(endVertex)){
				isDuplicateEdge=true;
			}
			if(!isDuplicateEdge){
				//endVertex.previousVertex=this;
				edgeList.add(new Edge(endVertex,weight));
				result=true;
			}
		}
			
		return result;
	}
	
	public boolean hasNeighbor(){
		return !edgeList.isEmpty();
	}
	protected  class Edge{
		//A-->B,then the "outerClass" which invokes the method "getEndVertex" 
		//is "A",the "endVertex" is "B"
		private Vertex endVertex;
		private double weight;
		
		protected Edge(Vertex endVertex,double weight){
			this.endVertex=endVertex;
			this.weight=weight;
		}
		protected Vertex getEndVertex(){
			return endVertex;
		}
		protected double getWeight(){
			return weight;
		}
		
	}
}
3
0
分享到:
评论

相关推荐

    图的深度广度遍历,关键路径和最短路径

    总结以上,图的深度优先和广度优先遍历是基础的图遍历方法,关键路径和最短路径算法则用于解决实际问题,如项目管理、网络优化等。邻接表法作为一种高效的数据结构,有助于我们更好地操作和理解图的性质。

    图的深度优先遍历与广度优先遍历(C语言实现)

    本篇文章将深入探讨两种主要的图遍历算法:深度优先遍历(DFS,Depth-First Search)和广度优先遍历(BFS,Breadth-First Search),并提供C语言的实现。 **深度优先遍历(DFS)** 深度优先遍历是一种递归的策略,...

    数据结构图的邻接矩阵,邻接表存储表示,图的深度优先搜索遍历,广度优先搜索遍历

    本主题主要涵盖了三种关键概念:邻接矩阵、邻接表以及图的两种遍历方法——深度优先搜索(DFS)和广度优先搜索(BFS)。 首先,邻接矩阵是一种表示图的数据结构,它是一个二维数组,其中的每个元素代表图中对应节点...

    邻接表实现无向图的建立与遍历,最小生成树以及最短路径

    遍历无向图有多种方式,包括深度优先搜索(DFS)和广度优先搜索(BFS)。DFS常使用栈来实现,从一个顶点出发,沿着边访问未访问过的顶点;BFS则用队列,先访问距离起点近的顶点。"quene.h"可能是定义队列的头文件,...

    深度优先遍历 广度优先遍历 Dijikstta

    深度优先遍历(DFS, Depth First Search)和广度优先遍历(BFS, Breadth First Search)是图论中两种重要的遍历算法,用于访问图的所有顶点。这两种方法各有特点,适用于不同的场景。 深度优先遍历是一种递归的搜索策略...

    图 深度遍历 广度遍历 基本操作

    在这个主题中,我们将深入探讨图的深度遍历(Depth-First Search, DFS)和广度遍历(Breadth-First Search, BFS)这两种遍历算法,以及它们在数据结构基本实验中的应用。 **1. 图的基本概念** 图由顶点(Vertex)...

    头歌数据结构图的邻接矩阵存储及遍历操作

    然而,对于稀疏图来说,邻接矩阵会占用大量的空间,这时可能需要考虑使用邻接表等其他存储方式。 图的遍历算法是图论中的基础概念之一,深度优先遍历和广度优先遍历各有优缺点,具体选择哪种遍历方法取决于实际应用...

    图的广度优先遍历算法

    根据给定文件的信息,我们可以详细地探讨一下“图的广度优先遍历算法”这一主题。广度优先遍历(Breadth-First Search,简称 BFS)是一种用于遍历或搜索树或图的算法。其特点是先访问离起始节点距离较近的所有节点,...

    数据结构--图的遍历及应用--思维导图.pdf

    图的遍历算法可以使用邻接表法或邻接矩阵法实现。邻接表法是用一个数组来存储图的边信息,邻接矩阵法是用一个矩阵来存储图的边信息。不同的算法有不同的实现方式和性能分析结果。 Dijkstra算法 Dijkstra算法是一种...

    广度优先遍历.zip

    广度优先遍历是一种基础的图和树遍历算法,它按照层次顺序访问节点,适用于多种问题,如最短路径、环路检测和层次遍历等。通过队列和颜色标记的数据结构,BFS能有效地处理这些问题,并且在许多情况下优于深度优先...

    数据结构 图的广度遍历

    2. **实现图的广度优先遍历算法** 3. **分析示例输入与输出** 4. **代码解析** ### 1. 理解图的广度优先遍历(BFS) **定义:** - 广度优先遍历是一种用于图的搜索算法。它按照层次顺序遍历图的所有顶点,即从根节点...

    数据结构实验三:图的操作与实现

    以任意结点 v 为起点,实现上述图的深度优先和广度优先遍历算法。 3、最小生成树的算法实现 利用普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法求上图的最小生成树,算法实现 代码必须有注释。 4、最短路径的算法实现 ...

    图遍历(深度和广度)

    图遍历主要有两种方法:深度优先搜索(DFS,Depth-First Search)和广度优先搜索(BFS,Breadth-First Search)。这两种算法在处理网络数据结构、树结构、搜索问题以及解决许多其他计算问题时都扮演着核心角色。 ##...

    图的遍历 C语言版

    BFS特别适用于寻找最短路径问题,比如在无权图中寻找两个节点间的最短路径。在C语言中,我们需要创建一个队列结构,并实现入队、出队操作来实现BFS。 在实际编程中,图通常使用邻接矩阵或邻接表来表示。邻接矩阵是...

    数据结构实验 图的遍历

    这里我们将详细讨论图的基本概念、遍历的重要性以及两种主要的遍历策略:深度优先搜索(DFS)和广度优先搜索(BFS)。 首先,我们需要理解图的基本构成。一个图由顶点(或节点)和边组成,边表示顶点之间的关系。图...

    zsrf.rar_图的遍历c语言

    在这个"zsrf.rar_图的遍历c语言"压缩包中,包含的"zsrf.doc"文档很可能是对C语言实现图的深度优先遍历(DFS, Depth First Search)和广度优先遍历(BFS, Breadth First Search)的实验代码及其分析报告。 1. **深度...

    数据结构第六章图.pdf

    图的遍历可以用深度优先遍历(DFS)和广度优先遍历(BFS)两种方式。深度优先遍历使用栈,时间复杂度为O(|V|+|E|)。广度优先遍历使用队列,时间复杂度为O(|V|+|E|)。 图的连通性 图的连通性可以用深度优先遍历或...

    数据结构课程设计作业: C++&Qt实现 校园导航系统 最短路径.zip

    DFS适用于无权图的遍历,但不保证找到最短路径;BFS在所有节点距离起点相同的情况下能找到最短路径,但不适用于带权重的图;Dijkstra算法则是解决带权重图中最短路径问题的经典算法,它可以找到从源节点到其他所有...

    图的存储结构和遍历

    //-----------------------图的邻接表存储表示------------------------ typedef struct ArcNode { int adjvex; //该弧所指向的顶点的位置 struct ArcNode *nextarc; //指向下一条弧的指针 InfoType *info; //该...

    深度优先搜索、广度优先搜索及其生成树

    通过对深度优先搜索、广度优先搜索及其生成树的介绍,我们可以看出这两种搜索方法在图遍历方面各有优势。DFS更适用于寻找特定路径或探索所有可能路径的问题,而BFS则更适合于寻找最短路径或分层遍历的问题。通过这两...

Global site tag (gtag.js) - Google Analytics