有向无环图(邻接矩阵和邻接表)

您所在的位置:网站首页 有向图邻接矩阵和邻接表 有向无环图(邻接矩阵和邻接表)

有向无环图(邻接矩阵和邻接表)

2024-02-01 04:42| 来源: 网络整理| 查看: 265

一、图的定义

图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:

                   G=(V,E)

其中:G表示一个图,V是图G中顶点的集合,E是图G中顶点之间边的集合。

注:

在线性表中,元素个数可以为零,称为空表;

在树中,结点个数可以为零,称为空树;

在图中,顶点个数不能为零,但可以没有边。

 

 

二、图的遍历

   图的遍历是在从图中某一顶点出发,对图中所有顶点访问一次且仅访问一次。

  图的遍历操作要解决的关键问题:

  ① 在图中,如何选取遍历的起始顶点?

  解决方案:从编号小的顶点开始 。

  在线性表中,数据元素在表中的编号就是元素在序列中的位置,因而其编号是唯一的; 在树中,将结点按层序编号,由于树具有层次性,因而其层序编号也是唯一的; 在图中,任何两个顶点之间都可能存在边,顶点是没有确定的先后次序的,所以,顶点的编号不唯一。 为了定义操作的方便,将图中的顶点按任意顺序排列起来,比如,按顶点的存储顺序。

  ② 从某个起点始可能到达不了所有其它顶点,怎么办?

  解决方案:多次调用从某顶点出发遍历图的算法。

  ③ 因图中可能存在回路,某些顶点可能会被重复访问,那么如何避免遍历不会因回路而陷入死循环。

  解决方案:附设访问标志数组visited[n] 。

  ④ 在图中,一个顶点可以和其它多个顶点相连,当这样的顶点访问过后,如何选取下一个要访问的顶点?

  解决方案:深度优先遍历和广度优先遍历。

  1、深度优先遍历

  基本思想 :

  ⑴ 访问顶点v;

  ⑵ 从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历;

  ⑶ 重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。

  2、广度优先遍历

  基本思想:

  ⑴ 访问顶点v;

  ⑵ 依次访问v的各个未被访问的邻接点v1, v2, …, vk;

  ⑶ 分别从v1,v2,…,vk出发依次访问它们未被访问的邻接点,并使“先被访问顶点的邻接点”先于“后被访问顶点的邻接点”被访问。直至图中所有与顶点v有路径相通的顶点都被访问到。

三、图的存储结构

    是否可以采用顺序存储结构存储图?

  图的特点:顶点之间的关系是m:n,即任何两个顶点之间都可能存在关系(边),无法通过存储位置表示这种任意的逻辑关系,所以,图无法采用顺序存储结构。

  如何存储图?

  考虑图的定义,图是由顶点和边组成的,分别考虑如何存储顶点、如何存储边。

  ①邻接矩阵(数组表示法)

  基本思想:用一个一维数组存储图中顶点的信息,用一个二维数组(称为邻接矩阵)存储图中各顶点之间的邻接关系。

  假设图G=(V,E)有n个顶点,则邻接矩阵是一个n×n的方阵,定义为:

 

 

 

以上内容转自https://www.cnblogs.com/smile233/p/8228073.html

上面的内容关于邻接矩阵讲得比较好,对邻接表没有讲解(图都可以通过邻接表和邻接矩阵存储)

邻接矩阵是不错的一种图存储结构,但是,对于边数相对顶点较少的图,这种结构存在对存储空间的极大浪费。因此,找到一种数组与链表相结合的存储方法称为邻接表。

邻接表的处理方法是这样的: (1)图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过,数组可以较容易的读取顶点的信息,更加方便。 (2)图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用单链表存储,无向图称为顶点vi的边表,有向图则称为顶点vi作为弧尾的出边表。 例如,下图就是一个无向图的邻接表的结构。

这里写图片描述

从图中可以看出,顶点表的各个结点由data和firstedge两个域表示,data是数据域,存储顶点的信息,firstedge是指针域,指向边表的第一个结点,即此顶点的第一个邻接点。边表结点由adjvex和next两个域组成。adjvex是邻接点域,存储某顶点的邻接点在顶点表中的下标,next则存储指向边表中下一个结点的指针。 对于带权值的网图,可以在边表结点定义中再增加一个weight的数据域,存储权值信息即可。如下图所示。

从图中可以看出,顶点表的各个结点由data和firstedge两个域表示,data是数据域,存储顶点的信息,firstedge是指针域,指向边表的第一个结点,即此顶点的第一个邻接点。边表结点由adjvex和next两个域组成。adjvex是邻接点域,存储某顶点的邻接点在顶点表中的下标,next则存储指向边表中下一个结点的指针。 对于带权值的网图,可以在边表结点定义中再增加一个weight的数据域,存储权值信息即可。如下图所示。

四.两者区别 对于一个具有n个顶点e条边的无向图 它的邻接表表示有n个顶点表结点2e个边表结点 对于一个具有n个顶点e条边的有向图 它的邻接表表示有n个顶点表结点e个边表结点 如果图中边的数目远远小于n2称作稀疏图,这是用邻接表表示比用邻接矩阵表示节省空间; 如果图中边的数目接近于n2,对于无向图接近于n*(n-1)称作稠密图,考虑到邻接表中要附加链域,采用邻接矩阵表示法为宜。

附上leetcode上关于有向无环图的应用的题,课表的安排没有用链表实现利用c++STL中的容器vector去实现。

class Solution { public: bool canFinish(int numCourses, vector& prerequisites) { vector indegree(numCourses,0);//入度表 vectorlis(numCourses,vector());//用vector来存储邻接表 for(auto v:prerequisites) { indegree[v[0]]++; lis[v[1]].push_back(v[0]); } queueq; //从入度为0的结点开始处理数据 for(auto i=0;i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3