图及其遍历方式--广度优先&深度优先

本文介绍了图的定义,包括无向图、有向图和带权重的图,并探讨了两种图的存储方式:邻接矩阵和邻接链表。接着详细阐述了广度优先遍历(BFS)和深度优先遍历(DFS)的工作原理,分析了它们的时间复杂度和空间复杂度,以及在实际问题中的应用,如社交网络中的人脉关系查找。
摘要由CSDN通过智能技术生成
  • 图的定义及其分类

  图和之前说的二叉树一样也是一种非线性数据结构,图由两部分组成:其一是顶点;其二是顶点之间连接的边。顶点就是图中的元素结点,而边就是用来表示顶点之间的关系,如下图:
在这里插入图片描述
每个顶点的边的条数就是顶点的度, 例如社交产品中,我们每一个人就是图中的顶点,而我们的好友就是该通过边直接连接的顶点,我们好友的个数就是顶点的度。
  上图所示的是一种图,它并没有方向的概念,我们知道有些关系之间是有方向的概念的,例如,微博中的关注关系,你关注了某个人但是这个人不一定关注了你。因此,这种图称为有向图, 例如下面所示的图:
在这里插入图片描述
在有向图中,如果某个顶点指向其他顶点的边的条数就称为该顶点的出度 ;如果某个顶点有多个顶点指向这个顶点,这就叫该顶点的入度 。对于这种指向关系,我们将边出发的顶点称为弧头,边到达的顶点称为弧尾。
  还有一种图,它仅仅用顶点和边描述还不够,例如当我们要给几个地方修几条公路,有几种方案,每一个地方到另一个地方修路的造价是不同的,那么对于这样的图就称为带权重的图,对于图就先说这几个概念,其实图还有许多其他的概念,我们以后再说
在这里插入图片描述

  • 图的存储方式

  图一般有两种存储方式,一种是邻接矩阵的方式;另一种是邻接链表的方式。邻接矩阵实际上就是一个二维数组,对于无向图来说,邻接矩阵是一个完全对称的矩阵,其中两个顶点之间如果存在边就记为1,否则就记为0;对于有向图来说,如果顶点 i 到顶点 j 之间,有一条箭头从顶点 i 指向顶点 j 的边,那我们就将 A[i][j]标记为 1;对于带权重的图就是矩阵中的值变为权重,如下图
在这里插入图片描述
  请试想一下邻接矩阵的存储方式有什么问题?假如用邻接矩阵存储图会造成空间的浪费,如果我们的图太过稀疏的话,就说明顶点很多但是顶点之间的关系很少也就是边很少,这样的话就会造成空间浪费。但是用邻接矩阵也有很多有点,邻接矩阵的存储方式简单、直接,因为基于数组,所以在获取两个顶点的关系时,就非常高效。其次,用邻接矩阵存储图的另外一个好处是方便计算。这是因为,用邻接矩阵的方式存储图,可以将很多图的运算转换成矩阵之间的运算。比如求解最短路径问题时,其中一种算法就是利用矩阵的运算完成。
  下面我们来看看邻接链表的存储方式,邻接链表就是一个顶点对应一个链表,链表中存储的是与这个顶点直接连接的其他顶点,我们来看看它的图示存储结构
在这里插入图片描述
邻接链表的存储方式虽然说比较节省了空间,但是在时间效率上就低了不少。假如我们需要从某个顶点查询是否存在某个顶点的关系,我们就需要从这个顶点出发,遍历那条对应的链表,因此遍历的时间复杂度为O(n),为了提高查找的执行效率我们可以采用将链表的结构改造为AVL树或者红黑树就能将复杂度降低为O(logn)。我们看看代码的实现(邻接链表的方式)

 // 无向图的邻接链表存储方式
public class Graph {
   
   // 顶点的个数
  private int v;
   // 邻接链表
  private LinkedList<Integer> adj[];

  public Graph(int v) {
   
    this.v = v;
    adj = new LinkedList[v];
    for (int i=0; i<v; ++i) {
   
      adj[i] = new LinkedList<>();
    }
  }

   // 由于无向图是双向的结果,因此需要进行两次结点的添加
  public void addEdge(int startNode, int searchNode) {
   
    adj
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值