图的引出:前面我们学了线性表和树。线性表局限于一个直接前驱和一个直接后继的关系;树也只能有一个直接前驱也就是父结点。但我们需要表示多对多的关系时,我们就需要用到图这种数据结构。

图的表示方式有两种:二维数组表示(邻接矩阵)链表表示(邻接表)

邻接矩阵中,如果两个顶点相连通,则为1,如果不连通,则为零。

图的遍历

有两种策略。1、深度优先遍历(Depth First Search)。2、广度优先遍历(Broad First Search)

深度优先遍历思想:深度优先遍历是一种纵向切入的思想。思想是先访问当前顶点,然后再以这个顶点作为初始顶点,访问该顶点的第一个邻接顶点。可以这样理解:每次访问完当前顶点后首先访问当前顶点的第一个邻接顶点。这样的访问策略是优先往纵向挖掘深入,而不是对一个结点的所有邻接结点进行横向访问。由此可以看出,需要通过递归来实现深度优先遍历

广度优先遍历思想:广度优先遍历类似于一个分层搜索的过程,广度优先遍历需要使用一个队列以保持访问过的节点的顺序,以便按这个顺序来访问这些结点的邻接结点。

接下来我举一个例子,讲述深度优先遍历的思想

接下来还是以同样一个例子讲述广度优先的遍历思想:

两者的区别:深度优先就是一直到底遍历;而广度优先就好似一张网,一步一步迈进遍历。

这是两者最主要的区别

深度优先遍历的步骤

  1. 访问初始结点v,并标记结点v为已访问。
  2. 查找结点v的第一个邻接结点w。
  3. 若w存在,则继续执行4,如果w不存在,则回到第1步,将从v的下一个结点继续。
  4. 若w未被访问,对w进行深度优先遍历递归(即把w当作另一个v,然后进行步骤123).
  5. 查找结点v的w邻接结点的下一个邻接结点,转到步骤3.

广度优先遍历的步骤

  1. 访问初始结点v并标记结点v为已访问。
  2. 结点v入队列
  3. 当队列非空时,继续执行,否则算法结束。
  4. 出队列,取得队列头结点u。
  5. 查找结点u的第一个邻接结点w。
  6. 若结点u的邻接结点w不存在,则转到步骤3;否则循环执行以下三个步骤:

6.1若结点w尚未被访问,则访问结点w并标记为已访问。

6.2结点w入队列。

6.3查找结点u的继w邻接结点后的下一个邻接结点w,转到步骤6。

具体实现代码附上,大家可以通过代码仔细去感悟。

package com.liu.chart;import java.util.ArrayList;
import java.util.LinkedList;/*** @author liuweixin* @create 2021-09-20 8:50*/
//图
public class VertexChart {ArrayList<String> VertexList;int[][] edges;//用来储存顶点之间的关系int numOfEdges;//表示边的个数public static void main(String[] args) {
//        String[] data = new String[]{"A", "B", "C", "D", "E"};String[] data = new String[]{"1", "2", "3", "4", "5", "6", "7", "8"};VertexChart vertexChart = new VertexChart(data.length);for (String value : data) {vertexChart.addVertex(value);}
//        vertexChart.addEdge(0,1,1);
//        vertexChart.addEdge(0,2,1);
//        vertexChart.addEdge(1,2,1);
//        vertexChart.addEdge(1,3,1);
//        vertexChart.addEdge(1,4,1);vertexChart.addEdge(0, 1, 1);vertexChart.addEdge(0, 2, 1);vertexChart.addEdge(1, 3, 1);vertexChart.addEdge(1, 4, 1);vertexChart.addEdge(2, 5, 1);vertexChart.addEdge(2, 6, 1);vertexChart.addEdge(3, 7, 1);vertexChart.addEdge(4, 7, 1);vertexChart.addEdge(5, 6, 1);vertexChart.show();System.out.println();vertexChart.dfs();//深度优先遍历:1-2-4-8-5-3-6-7System.out.println();vertexChart.bfs();//广度优先遍历:1-2-3-4-5-6-7-8}public VertexChart(int VertexCount) {edges = new int[VertexCount][VertexCount];VertexList = new ArrayList<String>(VertexCount);numOfEdges = 0;}/*** 对广度优先方法的封装*/public void bfs(){boolean[] isVisited = new boolean[VertexList.size()];//添加该循环的原因在于,有可能数据是分布在两张图甚至多张图上的,所以我们需要对所有的数据实现广度优先遍历//如果数据都分布在单一的一张图上,则不需要加此循环for (int i = 0; i < VertexList.size(); i++) {//对所有数据进行广度优先遍历if(!isVisited[i]){//判断是否访问过bfs(isVisited,i);//进行广度优先遍历}}}/***广度优先* @param isVisited 是否被访问* @param i  初始结点*/public void bfs(boolean[] isVisited, int i){int u;//表示队列的头结点对应的下标int w;//邻接结点w//队列,记录结点访问的顺序LinkedList queue = new LinkedList();//访问结点,输出结点信息System.out.print(VertexList.get(i)+ " ");//标记为已访问isVisited[i]=true;//将结点加入队列queue.addLast(i);while (!queue.isEmpty()){//取出队列的头结点下标u=(Integer)queue.removeFirst();//得到第一个邻接结点的下标ww=getFirstNeighbor(u);while (w!=-1){//找到//是否访问过if(!isVisited[w]){System.out.print(VertexList.get(w)+" ");//标记已经访问isVisited[w]=true;//入队queue.addLast(w);}//以u为前驱点,找w后面的下一个邻接点w=getNextNeighbor(u,w);//体现出广度优先.}}}//对深度优先遍历方法进行封装public void dfs() {boolean[] isVisited = new boolean[VertexList.size()];//添加该循环的原因在于,有可能数据是分布在两张图甚至多张图上的,所以我们需要对所有的数据实现深度优先遍历//如果数据都分布在单一的一张图上,则不需要加此循环for (int i = 0; i < VertexList.size(); i++) {//对所有数据进行深度优先遍历if(!isVisited[i]){//判断是否访问过dfs(isVisited, 0);//进行深度优先}}}/*** 深度优先遍历** @param isVisited 是否被访问* @param i         初始结点*/public void dfs(boolean[] isVisited, int i) {System.out.print(VertexList.get(i) + " ");isVisited[i] = true;//设置该点已被访问过//获取该结点的第一个邻接结点的下标int index = getFirstNeighbor(i);while (index != -1) {//如果循环能进来,此时表明有下一个邻接结点if (!isVisited[index]) {//如果该结点未被访问过//进行递归遍历+回溯dfs(isVisited, index);}//如果该结点已被访问过index = getNextNeighbor(i, index);}}/*** 根据前一个结点的邻接结点的下标获取下一个邻接结点** @param v1* @param v2* @return*/public int getNextNeighbor(int v1, int v2) {for (int i = v2 + 1; i < VertexList.size(); i++) {if (edges[v1][i] > 0) {return i;}}return -1;}/*** 得到该下标的第一个邻接结点** @param index* @return 如果找到,则返回该下标值,如果找不到,返回-1*/public int getFirstNeighbor(int index) {for (int i = 0; i < VertexList.size(); i++) {if (edges[index][i] == 1) {return i;}}return -1;}/*** 显示图的邻接矩阵*/public void show() {for (int[] arr : edges) {for (int data : arr) {System.out.print(data + " ");}System.out.println();}}/*** 获取顶点的个数** @return 返回顶点的个数*/public int getVexCount() {return VertexList.size();}/*** 获取边的个数** @return 返回边的个数*/public int getNumOfEdges() {return numOfEdges;}/*** 返回对应的两个顶点之间的关系** @param v1 第一个顶点的下标* @param v2 第二个顶点的下标* @return 如果返回1,则表示其可以连通;如果返回0,则表示其不连通*/public int getWeight(int v1, int v2) {return edges[v1][v2];}/*** 获取对应下标的顶点值** @param index 对应下标* @return 返回该顶点值*/public String getVertex(int index) {return VertexList.get(index);}/*** 把顶点的数据存储到List中** @param data*/public void addVertex(String data) {VertexList.add(data);}/*** 将顶点之间的关系进行表示** @param v1     表示点的下标,即第几个顶点* @param v2     第二个顶点对应的下边* @param weight 两者的关系。如果为1,则表示两者连通;如果为0,则表示两者不连通。*/public void addEdge(int v1, int v2, int weight) {edges[v1][v2] = weight;edges[v2][v1] = weight;numOfEdges++;}
}

图的深度优先遍历及广度优先遍历相关推荐

  1. 广度优先搜索生成树怎么画_图的深度优先遍历与广度优先遍历以及最小生成树...

    图的深度优先遍历 题目:写出附从每个顶点出发的一次深度优先搜索遍历序列.在纸上画出遍历过程和序列,提交截图. 错误回答 从A点开始遍历:0124-01324-0134-0324-034 从B点开始遍历 ...

  2. 大话数据结构 17:图的深度优先遍历和广度优先遍历

    深度优先遍历 主要思路是从图中一个未访问的顶点 V 开始,沿着一条路一直走到底,然后从这条路尽头的节点回退到上一个节点,再从另一条路开始走到底-,不断递归重复此过程,直到所有的顶点都遍历完成,它的特点 ...

  3. 图:图的邻接表创建、深度优先遍历和广度优先遍历代码实现

    邻接表介绍 邻接矩阵是不错的一种图存储结构,但是我们也发现,对于边数相对顶点较少的图,这种结构比较较浪费存储空间.如果不想浪费存储空间,大家肯定会先到链表.需要空间的时候再才想内存去申请,同样适用于图 ...

  4. 图:图的邻接矩阵创建、深度优先遍历和广度优先遍历详解

    邻接矩阵介绍 直接说,邻接矩阵是图的一种存储结构.那么图是什么呢?图是一种逻辑结构,和线性结构.树形结构.集合结构一样 是一种逻辑结构用来描述数据对象中的数据元素之间的关系.来看下图的定义:图(Gra ...

  5. 数据结构之图:邻接矩阵和邻接表、深度优先遍历和广度优先遍历

    简介 线性表是一种线性结构,除了头结点和尾节点,线性表的每个元素都只有一个前取节点和一个后继节点.而树结构则相较于线性表更加复杂,它描述的关系为数据元素之间的父子关系,也是现实世界父子关系的缩影, 一 ...

  6. 多级树的深度优先遍历与广度优先遍历(Java实现)

    目录 多级树的深度优先遍历与广度优先遍历(Java实现) 节点模型 深度优先遍历 广度优先遍历 多级树的深度优先遍历与广度优先遍历(Java实现) 深度优先遍历与广度优先遍历其实是属于图算法的一种,多 ...

  7. 数据结构—无向图创建邻接矩阵、深度优先遍历和广度优先遍历(C语言版)

    无向图创建邻接矩阵.深度优先遍历和广度优先遍历 一.概念解析: (1)无向图: (2)邻接矩阵: 二.创建邻接矩阵: 三.深度遍历.广度遍历 (1)深度遍历概念: (2)广度遍历概念: 四.实例展示 ...

  8. 实现教材算法7.2利用邻接矩阵构造无向图的算法,在此基础上进行深度优先遍历和广度优先遍历。

    软件学院实验报告 姓名:              学号:              专业:               年级: 课程名称 数据结构 实验名称 实验9.图的遍历 实验的准备阶段 实验内 ...

  9. 二叉树深度优先遍历和广度优先遍历

    二叉树深度优先遍历和广度优先遍历

  10. 二叉树的深度优先遍历和广度优先遍历

    二叉树是一种很重要的数据结构,对于二叉树的遍历,有深度优先遍历和广度优先遍历,深度优先遍历又有先序.中序.后续遍历,广度优先遍历就是按层遍历. 1. 深度优先遍历 深度优先遍历,也就是先序.中序.后续 ...

最新文章

  1. Leetcode 25 K个一组翻转链表 (每日一题 20210719)
  2. 使用 Arthas 排查 SpringBoot 诡异耗时的 Bug
  3. Vue3 高级语法(二)—— 自定义指令、Teleport、Vue插件
  4. python编译备忘
  5. 单片机c语言数字频率计的课程设计,课程设计基于单片机的简易数字频率计报告.doc...
  6. ViewBinding使用时出现Could not find method viewBinding() for arguments错误
  7. 收缩毛孔全过程,很详细! - 健康程序员,至尚生活!
  8. Yolov5如何在训练意外中断后接续训练
  9. java如何控制分屏显示,intellij idea 分屏设置 与快捷键
  10. JQuery事件绑定解绑方法小结
  11. 联想拯救者wif开不了_联想拯救者为什么连不上wifi
  12. 解锁高性能计算与区块链应用,阿里云Kubernetes服务召唤神龙
  13. 22个值得收藏的android开源代码-UI篇,kotlin类型转换
  14. 动态沙箱是威胁防御的关键所在
  15. 第二届计算机辅助教育国际大会,【回看】2019年第二届翻译教育国际研讨会 机助译员训练 (CATT): 人机之间...
  16. 在Linux下使用Vi进阶编辑器Vim编译C/C++
  17. 波比的w可以挡机器人的q_lol波比W可以挡哪些技能 波比W可以挡石头大招吗
  18. 青岛旅行规划及玩后感
  19. 智能硬件一键WIFI配置模式下,对路由设置比较敏感
  20. 华南理工大学网络教育计算机概论,华南理工大学网络教育学院2018计算机概论作业...

热门文章

  1. 域用户更改环境变更与关闭UAC
  2. 苹果显示器(Apple Cinema Display)亮度调节方法
  3. Struts2 教程 流程
  4. 这款神器,不仅仅解决你的证件照需求
  5. Android程序中如何启动浏览器
  6. 第24章 QSPI—读写串行FLASH
  7. 小项目1——猫眼Top100 爬取
  8. 读取cpu温度的api_获取CPU的温度的方法
  9. Win10下安装Ubuntu16.04-空间不可用-个人志
  10. 城通网盘仿蓝奏网盘源码