图的深度优先遍历(邻接表)

1.深度优先遍历

        图的深度优先遍历是从图的某个顶点出发,访问这个顶点,然后从v的没访问过的邻接点出发深度优先遍历图,直到图中所有和v有路径相通的顶点都被访问到。而以上是对应连通图而言,对于非连通图,先对它的连通分量进行深度优先遍历,,若图中还有顶点未被访问,则选择图中一个未曾被访问的顶点作为起始点,重复上述过程,直到图中全部顶点被访问。

《图的深度优先遍历(邻接表)》

假设从0开始进行未循环深度优先遍历,则顺序是这样:

《图的深度优先遍历(邻接表)》

        

0–>2–>1–>4  其中 访问1后,0已经被访问过了,所以回退

以下是这个图的邻接表表示:

《图的深度优先遍历(邻接表)》

由2个部分构成,顶点是由一个数组构成,边是由链表组成,以下给出实现

其中data表示顶点的数据frist表示顶点指向的第一条边

package graph;
/**
 * 邻接表的顶点
 * @author 798603812
 *
 */
public class Vertex<T> {
		private T date;
		private Edge frist;

		public T getDate() {
			return date;
		}
		public void setDate(T date) {
			this.date = date;
		}
		public Edge getFrist() {
			return frist;
		}
		public void setFrist(Edge frist) {
			this.frist = frist;
		}		
}

这里的vertexIndex代表这个边连接的第一个顶点下标,next代表下一个当前顶点的下一条边 

weigth是针对网图的权值。

package graph;
/**
 * 邻接表的边
 * @author 798603812
 *
 */
public class Edge {
	private int vertexIndex;
	private Edge next;
	private int weigth;
	public int getWeigth() {
		return weigth;
	}
	public void setWeigth(int weigth) {
		this.weigth = weigth;
	}
	public int getVertexIndex() {
		return vertexIndex;
	}
	public void setVertexIndex(int vertexIndex) {
		this.vertexIndex = vertexIndex;
	}
	public Edge getNext() {
		//System.out.println(next);
		if(next==null){
			return null;
		}
		return next;
	}
	public void setNext(Edge next) {
		this.next = next;
	}
}

实现代码

package graph;
/**
 * 深度优先遍历 	2017-12-21
 * @author 798603812
 *
 */
public class Dfs {
	/**
	 * 深度优先遍历
	 * @param arr邻接表
	 */
	public static void dfs(Vertex[] arr) {
		boolean[] b = new boolean[arr.length];
		System.out.println();			
		for (int j = 0, len = arr.length; j < len; j++) {
			//如果这个顶点没有被访问过
			;
			if (!b[j]) {
				fun(arr, j, b);				
			}
		}
			System.out.println();
	}	
	private static void fun(Vertex[] arr,int i,boolean[] b){
		b[i]=true;
		//System.out.println(i);
		System.out.print(arr[i].getDate()+"\t");
		Edge e=arr[i].getFrist();
		while(e!=null){//对i的第一条边的顶点进行访问
			if(!b[e.getVertexIndex()]){
				fun(arr, e.getVertexIndex(), b);
			}
			e=arr[e.getVertexIndex()].getFrist();
			if(b[e.getVertexIndex()]){
				break;
			}
			
		}
		e=arr[i].getFrist();
		if(e!=null&&e.getNext()!=null){	//对i坐标的顶点剩下的顶点进行访问
			e=e.getNext();
		}
		//1 2 1 3 2 4 3 5 5 4 4 6 6 7 7 5	
		while(e!=null){	
			if(!b[e.getVertexIndex()]){
				fun(arr, e.getVertexIndex(), b);
			}
			e=e.getNext();
			if(e==null||b[e.getVertexIndex()]){
				break;
			}
		}
		return;
	}
}

以下图做示范。这个方法访问顺序为0->2->1->5->7->6->4  然后第二轮循环  3

《图的深度优先遍历(邻接表)》《图的深度优先遍历(邻接表)》

测试:

快速生成邻接表的方法

package graph;

import java.util.Scanner;
/**
 * 初始化邻接表
 * @author 798603812
 *
 */
public class Set {
	/**
	 * 只针对无权图
	 * @param x   顶点的个数
	 * @param y	  边的个数
	 * @return	  邻接表
	 */
	public static Vertex[] set(int x,int y){
		//参考输入数据  1 2 3 4 5
		//1 3 1 2 1 4 1 5 2 5 2 4
			Scanner sc=new Scanner(System.in);
			Vertex[]arr=new Vertex[x];
			Vertex<String> v=null;
			System.out.println("请依次输入顶点的信息空格分开");
			for(int i=0;i<x;i++){
				String str=sc.next();
				v=new Vertex<String>();
				v.setDate(str);
				v.setFrist(null);
				arr[i]=v;
			}
			System.out.println("请依次输入边的信息空格分开 (根据你输入的顶点信息来)");
			Edge e=null;
			int str1,str2;
			//System.out.println(y);
			for(int j=0;j<y;j++){
				str1=sc.nextInt();
				str2=sc.nextInt();
				//System.out.println("str1:"+str1+"str2:"+str2);
				e=new Edge();
				e.setVertexIndex(str2-1);
				if(arr[str1-1].getFrist()==null){
					arr[str1-1].setFrist(e);				
				}else{
					Edge e2=arr[str1-1].getFrist();
					while(e2.getNext()!=null){
						e2=e2.getNext();
					}
					//System.out.println(e.getVertexIndex());
					e2.setNext(e);
				}	
			}
		return arr;		
	}
	/**
	 * 针对网图
	 * @param x   顶点的个数
	 * @param y	  边的个数
	 * @return	  邻接表
	 */
	public static Vertex[] net(int x,int y){
		//参考输入数据  1 2 3 4 5
		//1 3 1 2 1 4 1 5 2 5 2 4
			Scanner sc=new Scanner(System.in);
			Vertex[]arr=new Vertex[x];
			Vertex<String> v=null;
			System.out.println("请依次输入顶点的信息空格分开");
			for(int i=0;i<x;i++){
				String str=sc.next();			
				v=new Vertex<String>();
				v.setDate(str);				
				v.setFrist(null);
				arr[i]=v;
			}
			System.out.println("请依次输入边的信息空格分开 (根据你输入的顶点信息来) 然后输入权值");
			Edge e=null;
			int str1,str2,weigth;
			//System.out.println(y);
			for(int j=0;j<y;j++){
				str1=sc.nextInt();
				str2=sc.nextInt();
				 weigth=sc.nextInt();
				//System.out.println("str1:"+str1+"str2:"+str2);
				e=new Edge();
				e.setWeigth(weigth);
				e.setVertexIndex(str2);
				if(arr[str1].getFrist()==null){
					arr[str1].setFrist(e);				
				}else{
					Edge e2=arr[str1].getFrist();
					while(e2.getNext()!=null){
						e2=e2.getNext();
					}
					e2.setNext(e);
				}	
			}
		return arr;		
	}
}

package graph;

import java.util.Scanner;

public class Test {
	


	public static void main(String[] args) {
		Test t=new Test();
		Vertex<Integer>[]arr=Set.set(6, 6);
//		Search s=new Search();
//		s.shortest(arr, 0);
//		System.out.println("迪杰斯特拉算法");
//		for(int i=0;i<s.dis.length;i++){
//			System.out.print(s.dis[i]+"\t");
//		}
		System.out.println();
		System.out.println("深度优先遍历");
		Dfs.dfs(arr);
		System.out.println("宽度优先遍历");
		Bfs.bfs(arr);
//		Floyd f=new Floyd();
//		System.out.println("弗洛伊德算法");
//		f.floyd(arr);
		//Prim p=new Prim();
		//System.out.println("普里姆算法");
		//p.prim(arr, 1);
		/**
		 请依次输入顶点的信息空格分开
1 2 3 4 5 6 7 8
请依次输入边的信息空格分开 (根据你输入的顶点信息来)
1 5 1 3 2 1 3 2 3 5 4 2 7 5 6 7 7 6
		 * 
		 */
	}
}

输入的数据:(顶点初始值需大于0 因为我写的那个快速生成邻接表的方法导致)

请依次输入顶点的信息空格分开
1 2 3 4 5 6
请依次输入边的信息空格分开 (根据你输入的顶点信息来)
1 2 1 3 4 3 2 5 3 6 2 6

结果

1 2 5 6 3 4

这个图为

《图的深度优先遍历(邻接表)》

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/qq_38612955/article/details/79931704
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞