前言

本文主要讲解 数据结构中的图 结构,包括 深度优先搜索(DFS)、广度优先搜索(BFS)、最小生成树算法等,希望你们会喜欢。


目录


1. 简介

  • 数据结构的中属于 圆形结构 的逻辑结构
  • 具体介绍如下


2. 基础概念

  • 在图的数据结构中,有许多基础概念,如 边类型、图顶点 & 边间的关系等等
  • 具体请看下图


3. 类型

图的类型分为很多种,具体如下:

3.1 有向图 & 无向图

3.2 连通图

  • 定义
    图中任意顶点都是连通的图

  • 具体相关概念
    对于有向图 & 无向图,连通图的的具体概念又不同,具体如下

对于无向图:

对于有向图:

3.3 其余类型图


4. 存储结构

图的存储结构共有5种,具体请看下图


5. 图的遍历

数据结构:图文详解二叉树(遍历、类型、操作)

5.1 定义

从图中某1顶点出发,遍历图中其余所有顶点 & 使每1个顶点仅被访问1次

5.2 遍历方式

深度优先遍历(DFS)、广度优先遍历(BFS

5.3 具体介绍

5.3.1 深度优先遍历( DFS )
  • 简介

  • 算法示意图

  • 具体实现:递归 & 非递归

此处图的存储结构 = 邻接矩阵

import java.util.Stack;public class MyGraph {/*** 准备工作1:设置变量*/private int vexnum;  // 存放图中顶点数量private char[] vertices;  // 存放结点数据private int [][] arcs;  // 存放图的所有边private boolean[] visited;// 记录节点是否已被遍历/*** 准备工作2:初始化图的顶点数量、数据 & 边*/public MyGraph(int n){vexnum = n;vertices = new char[n];visited = new boolean[n];arcs = new int[n][n];}/*** 图的深度优先遍历算法实现:递归* 类似 前序遍历*/public void DFSTraverse(){// 1. 初始化所有顶点的访问标记// 即,都是未访问状态for (int i = 0; i < vexnum; i++) {visited[i] = false;}// 2. 深度优先遍历顶点(从未被访问的顶点开始)for(int i=0;i < vexnum;i++){if(visited[i]==false){// 若是连通图,只会执行一次traverse(i); // ->>看关注1}}}/*** 关注1:邻接矩阵的深度优先搜索递归算法* 即,从第i个顶点开始深度优先遍历*/private void traverse(int i){// 1. 标记第i个顶点已遍历visited[i] = true;// 2. (输出)访问当前遍历的顶点visit(i);// 3. 遍历邻接矩阵中第i个顶点的所有邻接顶点for(int j=0;j<vexnum;j++){// a. 若当前顶点的邻接顶点存在 & 未被访问,则递归 深度优先搜索 算法if(arcs[i][j]==1 && visited[j]==false){// b. 将当前顶点的邻接顶点作为当前顶点,递归 深度优先搜索 算法traverse(j);}}}/*** 辅助算法1:访问顶点值*/public void visit(int i){System.out.print(vertices[i] + " ");}/*** 图的深度优先遍历算法实现:非递归* 原理:采用 栈实现*/public void DFSTraverse2(){// 1. 初始化顶点访问标记// 全部标记为:未访问for (int i = 0; i < vexnum; i++) {visited[i] = false;}// 2. 创建栈Stack<Integer> s = new Stack<Integer>();for(int i=0 ; i<vexnum; i++){// 3. 若该顶点未被访问if(!visited[i]){// 4. 入栈该顶点s.add(i);do{// 出栈int curr = s.pop();// 如果该节点还没有被遍历,则遍历该节点并将子节点入栈if(visited[curr]==false){// 遍历并打印visit(curr);visited[curr] = true;// 没遍历的子节点入栈for(int j=vexnum-1; j>=0 ; j-- ){if(arcs[curr][j]==1 && visited[j]==false){s.add(j);}}}}while(!s.isEmpty());}}}/*** 测试(递归 & 非递归)*/public static void main(String[] args) {// 1. 初始化图的结构(顶点数量 = 9)MyGraph g = new MyGraph(9);// 2. 设置顶点数据char[] vertices = {'A','B','C','D','E','F','G','H','I'};g.setVertices(vertices);// 3. 设置边g.addEdge(0, 1);g.addEdge(0, 5);g.addEdge(1, 0);g.addEdge(1, 2);g.addEdge(1, 6);g.addEdge(1, 8);g.addEdge(2, 1);g.addEdge(2, 3);g.addEdge(2, 8);g.addEdge(3, 2);g.addEdge(3, 4);g.addEdge(3, 6);g.addEdge(3, 7);g.addEdge(3, 8);g.addEdge(4, 3);g.addEdge(4, 5);g.addEdge(4, 7);g.addEdge(5, 0);g.addEdge(5, 4);g.addEdge(5, 6);g.addEdge(6, 1);g.addEdge(6, 3);g.addEdge(6, 5);g.addEdge(6, 7);g.addEdge(7, 3);g.addEdge(7, 4);g.addEdge(7, 6);g.addEdge(8, 1);g.addEdge(8, 2);g.addEdge(8, 3);// 4. 执行 图的深度优先遍历:(递归 & 非递归)System.out.println("深度优先遍历(递归)");g.DFSTraverse();System.out.println("深度优先遍历(非递归)");g.DFSTraverse2();}/*** 辅助算法1:添加边(无向图)*/public void addEdge(int i, int j) {// 边的头尾不能为同一节点if (i == j) return;// 将邻接矩阵的第i行第j列的元素值置为1;arcs[i][j] = 1;// 将邻接矩阵的第j行第i列的元素值置为1;arcs[j][i] = 1;// 设置为1代表2顶点之间存在 边 (设置相等原因 = 邻接矩阵 是对称的)}/*** 辅助算法2:设置顶点数据*/public void setVertices(char[] vertices) {this.vertices = vertices;}
}
  • 测试结果
深度优先遍历(递归)
A B C D E F G H I
深度优先遍历(非递归)
A B C D E F G H I
  • 特别注意
    对于图的存储结构 = 邻接表实现,只需要将 存储边 的2维数组 改成链表即可。

  • 图的存储结构 = 邻接矩阵 / 邻接表 的性能对比

5.3.2 广度优先遍历(BFS)
  • 简介

  • 算法示意图

  • 具体流程

注:GI 先访问的原因 = 用数组存储顶点时,G的下标 比 I的下标小(按ABCDEFGHI顺序存储)

  • 具体实现

非递归:采用队列

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;public class MyGraph {/*** 准备工作1:设置变量*/private int vexnum;  // 存放图中顶点数量private char[] vertices;  // 存放结点数据private int [][] arcs;  // 存放图的所有边private boolean[] visited;// 记录节点是否已被遍历/*** 准备工作2:初始化图的顶点数量、数据 & 边*/public MyGraph(int n){vexnum = n;vertices = new char[n];visited = new boolean[n];arcs = new int[n][n];}/*** 广度优先搜索 算法实现* 原理:非递归(采用队列)*/public void BFS(){// 1. 初始化所有顶点的访问标记// 即,设置为未访问状态for (int i = 0; i < vexnum; i++) {visited[i] = false;}// 2. 创建队列Queue<Integer> q=new LinkedList<Integer>();// 3. 对所有顶点做遍历循环(从第1个顶点开始)// 若遍历完毕,则结束整个层序遍历for(int i=0;i < vexnum;i++){// 4. 若当前顶点未被访问,就进行处理// 若当前顶点已被访问,则回到3进行判断if( visited[i]==false ) {// 5. (输出)访问当前顶点visit(i);// 6. 标记当前顶点已被访问visited[i] = true;// 7. 入队当前顶点q.add(i);// 8.判断当前队列是否为空// 若为空则跳出循环,回到3进行判断while(!q.isEmpty()) {// 9. 出队队首元素 & 将出队的元素 赋值为 当前顶点i =  q.poll();// 10. 遍历当前顶点的所有邻接点// 若遍历完毕,则回到8判断for(int j=0; j< vexnum ; j++){// 11. 若当前顶点的邻接顶点存在 & 未被访问,则执行处理// 否则回到10判断if(arcs[i][j]==1 && visited[j]==false){// 12. (输出)访问当前顶点的邻接顶点visit(j);// 13. 标记当前顶点的邻接顶点已被访问visited[j] = true;// 14. 入队当前顶点的邻接顶点q.add(j);}}}}}}/*** 辅助算法1:访问该顶点*/public void visit(int i){System.out.print(vertices[i] + " ");}/** * 测试算法*/public static void main(String[] args) {// 1. 初始化图的结构(顶点数量 = 9MyGraph g = new MyGraph(9);// 2. 设置顶点数据char[] vertices = {'A','B','C','D','E','F','G','H','I'};g.setVertices(vertices);// 3. 设置边g.addEdge(0, 1);g.addEdge(0, 5);g.addEdge(1, 0);g.addEdge(1, 2);g.addEdge(1, 6);g.addEdge(1, 8);g.addEdge(2, 1);g.addEdge(2, 3);g.addEdge(2, 8);g.addEdge(3, 2);g.addEdge(3, 4);g.addEdge(3, 6);g.addEdge(3, 7);g.addEdge(3, 8);g.addEdge(4, 3);g.addEdge(4, 5);g.addEdge(4, 7);g.addEdge(5, 0);g.addEdge(5, 4);g.addEdge(5, 6);g.addEdge(6, 1);g.addEdge(6, 3);g.addEdge(6, 5);g.addEdge(6, 7);g.addEdge(7, 3);g.addEdge(7, 4);g.addEdge(7, 6);g.addEdge(8, 1);g.addEdge(8, 2);g.addEdge(8, 3);// 4. 执行 图的广度优先遍历(非递归)System.out.print("广度优先遍历(非递归):");g.BFS();}/*** 辅助算法1:添加边(无向图)*/public void addEdge(int i, int j) {// 边的头尾不能为同一节点if (i == j) return;// 将邻接矩阵的第i行第j列的元素值置为1;arcs[i][j] = 1;// 将邻接矩阵的第j行第i列的元素值置为1;arcs[j][i] = 1;// 设置为1代表2顶点之间存在 边 (设置相等原因 = 邻接矩阵 是对称的)}/*** 辅助算法2:设置顶点数据*/public void setVertices(char[] vertices) {this.vertices = vertices;}}
  • 执行结果
广度优先遍历(非递归):A B F C G I E D H

5.4 遍历方式对比


6. 最小生成树

本节主要讲解 图中的 最小生成树

6.1 定义

构造 连通网图 的最小成本生成树

  1. 网图:带有权值的图
  2. 最小成本:用(n-1)条边将 含n个顶点的连通图 连接起来 & 使得权值和最小

6.2 寻找最小生成树的算法

  • 主要包括:(Prim)普利姆算法 & (Kruskal)克鲁斯卡尔算法
  • 具体介绍如下

6.2.1 (Prim)普利姆算法

  • 算法概述

  • 算法原理流程示意图

  • 举例说明

6.2.2(Kruskal)克鲁斯卡尔算法

  • 算法概述

6.3 算法对比


7. 最短路径

7.1 定义

  • 对于非网图(无权值),最短路径 = 两顶点间经过的边数最少的路径
  • 对于网图(有权值):最短路径 = 两顶点间经过的边上权值和最少的路径

第1个顶点 = 源点、第2个顶点 = 终点

7.2 需解决的问题

从源点 -> 其余各顶点的最短路径

7.3 寻找最短路径 算法

  • 主要包括:迪杰斯特拉算法(Dijkstra)、弗洛伊德算法(Floyd)

  • 具体介绍如下


8. 总结

  • 本文主要讲解了数据结构中的图
  • 下面我将继续对 数据结构,有兴趣可以继续关注Carson_Ho的安卓开发笔记

帮顶 / 评论点赞!因为你的鼓励是我写作的最大动力!

Carson带你学数据结构:手把手带你了解 ”图“ 所有知识!(含DFS、BFS)相关推荐

  1. 【数据结构与算法分析】0基础带你学数据结构与算法分析09--线索二叉树 (TBT)

    目录 TBT 的存储结构 线索化 如果一棵二叉树,所有原本为空的右孩子改为指向该结点的中序遍历的后继,所有原本为空的左孩子改为指向该结点的中序遍历的前驱,那么修改后的二叉树被称为 线索二叉树 (Thr ...

  2. 数据结构实验之图论三:判断可达性(dfs/bfs)

    Description 在古老的魔兽传说中,有两个军团,一个叫天灾,一个叫近卫.在他们所在的地域,有n个隘口,编号为1-n,某些隘口之间是有通道连接的.其中近卫军团在1号隘口,天灾军团在n号隘口.某一 ...

  3. Carson带你学Android:RxJava过滤操作符

    前言 Rxjava由于其基于事件流的链式调用.逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎. 今天,我将为大家详细介绍RxJava操作符中最常用的 过滤操作符,希望你们会 ...

  4. Carson带你学Android:图文详解RxJava背压策略

    前言 Rxjava,由于其基于事件流的链式调用.逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎. 本文主要讲解的是RxJava中的 背压控制策略,希望你们会喜欢. Cars ...

  5. 最后一期:如何更新LSTM模型?(附代码)| 博士带你学LSTM

    最后一期:如何更新LSTM模型?(附代码)| 博士带你学LSTM LSTM是一种时间递归神经网络,适合于处理和预测时间序列中间隔和延迟相对较长的重要事件.在自然语言处理.语言识别等一系列的应用上都取得 ...

  6. python基础入门(Peak带你学python)

    带你学python Peak带你学python 基础语法知识 print函数 转义字符 进制转换 保留字和标识符 变量 数据类型 数据类型转换 注释 input函数 运算符 运算符优先级 布尔值 if ...

  7. Carson带你学Android:手把手带你入门跨平台UI开发框架Flutter

    前言 Flutter 作为Google出品的一个新兴的跨平台移动客户端UI开发框架,正在被越来越多的开发者和组织使用,包括阿里的咸鱼.腾讯的微信等. 今天,我将献上一份 <全面 & 详细 ...

  8. Carson带你学Android:请收好这一份全面详细的Android学习指南

    前言 如果你也学习Android,那么你大概率会看过我的文章.经常有读者给我留言:"该怎么学习Android?"."日常学习Android的方法是什么". 今天 ...

  9. Carson带你学Android:你要的WebView与 JS 交互方式都在这里了

    前言 现在很多App里都内置了Web网页(Hybrid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 上述功能是由Android的WebView实现的,其中涉及到Android客户端与 ...

最新文章

  1. unix 查询进程并中止
  2. (原創) 將map輸出到cout,是否有更方便的方法? (C/C++) (STL)
  3. Tensorflow学习: 乘法demo
  4. 如何使用来电盒--宇然电脑公司管理软件
  5. tomcat手动发布
  6. vcf文件(call variants得来的)怎么看变异是纯合还是杂合的
  7. python中dic_python之dic {字典}(重要指数*****)
  8. C# 获取CPU序列号、MAC地址、硬盘ID等系统信息
  9. VS2005 工程在win7下使用管理员权限运行
  10. 接口交互时的URL带有日期格式的参数,注意拼装地址中的特殊符号(如空格等)
  11. python做算法题_Python 笔试常见基础算法题
  12. 程序猿趣图几张,第一张就亮瞎了..
  13. ECharts 前端数据可视化
  14. 今天身边的一个好友想的一个点子,可能会颠覆传统电商网,称为线上商店和线下商店的最后收割者
  15. 无卷积!金字塔视觉Transformer(PVT):用于密集预测的多功能backbone
  16. 【HTTP图片服务器】【项目记录2】:安装、配置MySQL环境
  17. 2012-2013年世界大学计算机专业排名
  18. Mac M1芯片安装 MySQL
  19. 软件项目管理第二篇:项目计划 (1)——范围计划
  20. 做出刷屏文字的6大哲学

热门文章

  1. 21_RS485简单讲解
  2. android自动划屏实现,OSC首发:android中的左右滑屏实现By ViewPager
  3. 大数据带来新机遇:如何利用大数据技术优化跨境电商运营?
  4. 下列不能用作存储容量单位的是
  5. 小微-你的专属聊天机器人
  6. qq远程控制 总是提示权限不足
  7. SpringBoot微信小程序授权登录
  8. 几何分布的期望公式的推导
  9. 食物也疯狂!KOOCAN盘点因为食物毁掉的中国电视剧
  10. 《测量心理学》技能部分考题分析