Java 由浅入深带你掌握图的遍历

目录
  • 1.图的遍历
  • 2.深度优先遍历
  • 3.利用DFS判断有向图是否存在环
  • 4.广度优先遍历

1.图的遍历

从图中某一顶点出发访问图中其余顶点,且每个顶点仅被访问一次

图的遍历有两种深度优先遍历DFS、广度优先遍历BFS

2.深度优先遍历

深度优先遍历以深度为优先进行遍历,简单来说就是每次走到底。类似于二叉树的前序遍历

思路:

1.以某一个顶点为起点进行深度优先遍历,并标记该顶点已访问

2.以该顶点为起点选取任意一条路径一直遍历到底,并标记访问过的顶点

3.第2步遍历到底后回退到上一个顶点,重复第2步

4.遍历所有顶点结束

根据遍历思路可知,这是一个递归的过程,其实DFS与回溯基本相同。

遍历:

以此图为例进行深度优先遍历

	static void dfs(int[][] graph,int idx,boolean[]visit) {
		int len = graph.length;
		//访问过
	 if(visit[idx]) return;
	 //访问该顶点
	 System.out.println("V"+idx);
	 //标志顶点
	 visit[idx] = true;
	 for(int i = 1;i < len;i++) {
	 //访问该顶点相连的所有边
		 if(graph[idx][i] == 1) {
	 //递归进行dfs遍历
		 dfs(graph, i, visit);
		 }
	 }

	}

遍历结果:

V1

V2

V3

V4

V5

V6

V7

V8

V9

创建图的代码:

public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		//顶点数 以1开始
		int n = scanner.nextInt();
		int[][] graph = new int[n+1][n+1];
		//边数
		int m = scanner.nextInt();

		for(int i = 1;i <= m;i++) {
			int v1 = scanner.nextInt();
			int v2 = scanner.nextInt();
			graph[v1][v2] = 1;
			graph[v2][v1] = 1;
		}

		//标记数组 false表示未访问过
		boolean[] visit = new boolean[n+1];
		dfs(graph, 1, visit);

	}

3.利用DFS判断有向图是否存在环

思路:遍历某一个顶点时,如果除了上一个顶点之外,还存在其他相连顶点被访问过,则必然存在环

	//默认无环
   static boolean flag = false;
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		//顶点数 以1开始
		int n = scanner.nextInt();
		int[][] graph = new int[n+1][n+1];
		//边数
		int m = scanner.nextInt();

		for(int i = 1;i <= m;i++) {
			int v1 = scanner.nextInt();
			int v2 = scanner.nextInt();
			graph[v1][v2] = 1;

		}
	 //标记数组 true为访问过
		boolean[] visit = new boolean[n+1];
		dfs(graph, 1, visit,1);
		if(flag)
			System.out.println("有环");

	}

	static void dfs(int[][] graph,int idx,boolean[]visit,int parent) {
		int len = graph.length;

	 System.out.println("V"+idx);
	 //标记顶点
	 visit[idx] = true;
	 for(int i = 1;i < len;i++) {
		 //访问该顶点相连的所有边
		 if(graph[idx][i] == 1) {
		 if( !visit[i] ) {
		 dfs(graph, i, visit,idx);
		 }
		 else if(idx != i) {
			 flag = true;
		 }
		 }
	 }

	}

注意:是有向图判断是否存在环,无向图判断是否存在环无意义,因为任意两个存在路径的顶点都可以是环

4.广度优先遍历

广度优先遍历是以广度(宽度)为优先进行遍历。类似于二叉树的层序遍历

思路:

1.以某一个顶点为起点进行广度优先遍历,并标记该顶点已访问

2.访问所有与该顶点相连且未被访问过的顶点,并标记访问过的顶点

3.以第2步访问所得顶点为起点重复1、2步骤

4.遍历所有顶点结束

通过队列来辅助遍历,队列出队顺序即是广度优先遍历结果

遍历

以此图为例,采用邻接矩阵的方式创建图,进行BFS遍历

	static void bfs(int[][] graph) {
		int len = graph.length;
		//标记数组 false表示未访问过
		boolean[] visit = new boolean[len];
		//辅助队列
		Queue<Integer> queue = new LinkedList<>();

		queue.offer(1);
		visit[1] = true;

		while(!queue.isEmpty()) {
			int num = queue.poll();
			System.out.println("V"+num);

			//遍历该顶点所有相连顶点
			for(int i = 1;i < len;i++) {
				//相连并且没有被访问过
				if(graph[num][i] == 1 && !visit[i]) {
					queue.offer(i);
					visit[i] = true;
				}
			}
		}
	}

遍历结果:

V1

V2

V6

V3

V7

V9

V5

V4

V8

创建图的代码

public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		//顶点数 以1开始
		int n = scanner.nextInt();
		int[][] graph = new int[n+1][n+1];
		//边数
		int m = scanner.nextInt();

		for(int i = 1;i <= m;i++) {
			int v1 = scanner.nextInt();
			int v2 = scanner.nextInt();
			graph[v1][v2] = 1;
			graph[v2][v1] = 1;
		}
		bfs(graph);
	}

到此这篇关于Java 由浅入深带你掌握图的遍历的文章就介绍到这了,更多相关Java 图的遍历内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 基于Java实现的图的广度优先遍历算法

    本文以实例形式讲述了基于Java的图的广度优先遍历算法实现方法,具体方法如下: 用邻接矩阵存储图方法: 1.确定图的顶点个数和边的个数 2.输入顶点信息存储在一维数组vertex中 3.初始化邻接矩阵: 4.依次输入每条边存储在邻接矩阵arc中 输入边依附的两个顶点的序号i,j: 将邻接矩阵的第i行第j列的元素值置为1: 将邻接矩阵的第j行第i列的元素值置为1: 广度优先遍历实现: 1.初始化队列Q 2.访问顶点v:visited[v]=1;顶点v入队Q; 3.while(队列Q非空) v=队列

  • Java 由浅入深带你掌握图的遍历

    目录 1.图的遍历 2.深度优先遍历 3.利用DFS判断有向图是否存在环 4.广度优先遍历 1.图的遍历 从图中某一顶点出发访问图中其余顶点,且每个顶点仅被访问一次 图的遍历有两种深度优先遍历DFS.广度优先遍历BFS 2.深度优先遍历 深度优先遍历以深度为优先进行遍历,简单来说就是每次走到底.类似于二叉树的前序遍历 思路: 1.以某一个顶点为起点进行深度优先遍历,并标记该顶点已访问 2.以该顶点为起点选取任意一条路径一直遍历到底,并标记访问过的顶点 3.第2步遍历到底后回退到上一个顶点,重复第

  • Java由浅入深带你了解什么是包package

    目录 什么是包 1.导入包中的类 2.静态导入 3.将类放到包中 4.包的访问权限控制 5.常见的系统包 什么是包 包 (package) 是组织类的一种方式. 使用包的主要目的是保证类的唯一性. 例如, 你在代码中写了一个 Test 类. 然后你的同事也可能写一个 Test 类. 如果出现两个同名的类, 就会冲突, 导致 代码不能编译通过 1.导入包中的类  Java 中已经提供了很多现成的类供我们使用 ①:例如打印数组: public class TestDemo{ public stati

  • Java由浅入深带你精通继承super

    目录 什么是继承 背景 super关键字 protected 关键字 final 关键字 什么是继承 面向对象的特征: 封装:不必要公开的数据成员和方法,使用private关键字进行修饰.意义:安全性. 背景 代码中创建的类, 主要是为了抽象现实中的一些事物(包含属性和方法). 有的时候客观事物之间就存在一些关联关系, 那么在表示成类和对象的时候也会存在一定的关联 例如, 设计一个类表示动物 注意,:我们可以给每个类创建一个单独的 java 文件. 类名必须和 .java 文件名匹配(大小写敏感

  • Java由浅入深讲解继承上

    目录 1.什么是继承 2.继承的细节 2.1super关键字 2.2子类的构造方法 2.3super和this区别 继承同样是面向对象程序的特点 1.什么是继承 所谓继承就是抽取类的共性,进而实现代码的复用 继承的关键字是extends 现在定义一个类Tree,里面有树的名字.来源和科属,方法是打印树的形态特征,如下: class Tree { String name; String source; String genu; public void trait() { } } 上面的类除了方法t

  • Java由浅入深学习数组的使用

    目录 一.前言 二.数组的定义 1.概述 2.静态初始化数组 3.动态初始化数组 4.总结 三.数组的属性 1.访问 2.长度 3.遍历 四.内存图 1.单数组内存图 2.多数组内存图 3.数组指向相同内存 五.常见问题 1.索引越界 2.空指针异常 一.前言 学习概述:前八天我们学习了语法基础.运算符与表达式.循环结构.分支结构,今天主要学习数组的定义.相关的属性方法.数组存储的内存图.常见错误 学习目标:掌握数组的两种定义方法.相关属性.了解内存原理.错误解决 二.数组的定义 1.概述 假如

  • 【JS+CSS3】实现带预览图幻灯片效果的示例代码

    一.前期准备 1.1 案例分析 适用场景:单例布局 1.2 方法论 V视图 HTML+CSS+调试 C js实现控制流程 D数据 优化扩展 二.代码 结构 <div class="slider"><!-- 特效区 --> <div class="main"><!-- 主视图区 --> <div class="main_i"> <div class="caption&quo

  • Python算法之图的遍历

    本节主要介绍图的遍历算法BFS和DFS,以及寻找图的(强)连通分量的算法 Traversal就是遍历,主要是对图的遍历,也就是遍历图中的每个节点.对一个节点的遍历有两个阶段,首先是发现(discover),然后是访问(visit).遍历的重要性自然不必说,图中有几个算法和遍历没有关系?! [算法导论对于发现和访问区别的非常明显,对图的算法讲解地特别好,在遍历节点的时候给节点标注它的发现节点时间d[v]和结束访问时间f[v],然后由这些时间的一些规律得到了不少实用的定理,本节后面介绍了部分内容,感

  • Java中二叉树的建立和各种遍历实例代码

    这是个常见的面试题,比如说通过二叉树的先序和中序遍历,得到二叉树的层序遍历等问题 先序+中序->建树 假设现在有个二叉树,如下: 此时遍历顺序是: PreOrder: GDAFEMHZ InOrder: ADEFGHMZ PostOrder: AEFDHZMG 现在给出先序(preOrder)和中序(InOrder),建立一颗二叉树 或者给出中序(InOrder)和后序(PostOrder), 建立二叉树,其实是一样的 树节点的定义: class Tree{ char val; Tree lef

  • Java 给图片和动图添加水印的方法

    这两天根据需求在做图片上传添加水印,实话说重来不知道java还可以这样操作,既然有个这要求我就去找资料研究了一番,现在把它分享一下,希望能帮到有需要的兄弟. 给普通图片添加水印和给动图添加水印是不一样的,给普通图片添加水印用的是java自带的方法写的,给动图使用了gif4j框架,这个框架在CSDN里面很多可以下载,建议下载破解版的,因为原来的jar包会有自带的一个水印是去不了的. import java.awt.*; import java.awt.image.BufferedImage; im

  • Java实现简单的扫雷图

    用Java实现简单的扫雷图,供大家参考,具体内容如下 扫雷图的思想是: 1.地图可以是一个二维数组,并对数组进行初始化 2.随机生成雷的位置,可以用Random函数进行随机生成也可以用Math.random()进行随机生成 (PS:我就是简单随机下标生成了雷的位置) 3.对每一个非雷的位置一周的格子进行判断是否有雷,进行数字的累加 4.遍历数组进行输出 private static void mineClearance() { // 声明一个二维数组表示扫雷地图 String[][] mineC

随机推荐