数据结构学习总结--图


图的定义

定义:图是由两个集合V和E组成的,记为\(G=(V,E)\),其中V是顶点的有穷非空集合,E是V中顶点偶对的有穷集合,这些顶点偶对称为边。\(V(G)\)\(E(G)\)通常表示图G的顶点集合和边集合,E(G)可以为空集 若E(G)为空 则图G只有顶点而没有边。
有向图:若边集E(G)为有向边的集合则称该图为有向图;
无向图:若边集E(G)为无向边的集合则称该图为无向图;

有向图的表示\(\color{red}{在有向图中顶点对<x,y>是有序的}\) <x,y>与<y,x>是不同的两条边 顶点对用一对尖括号括起来,x是有向边的始点,y是有向边的终点,<x,y>也称作一条弧,x为弧尾,y为弧头。
无向图的表示\(\color{red}{顶点对<x,y>是无序的}\),它称为与顶点x与顶点y相关连的一条边,无向图的顶点对用一对圆括号表示。

图的基本术语

(n表示图中顶点数目,用表示边的数目)
1.子图:假设有两个图G=(V,E)和G'=(V',E'),如果V'包含于V且E'包含于E,则称G'为G的子图

2. 无向完全图和有向完全图:对于无向图,若具有\(n*(n-1)/2\)条边 则称为无向完全图。对于有向图,若具有\(n*(n-1)\)条弧,则称为有向完全图。

  1. 稀疏图和稠密图:有很少条边或弧的图称为稀疏图,反之称为稠密图。

  2. 权和网:每条边可以标上具有某种含义的数值,该数值称为该边上的权。这些权可以表示从一个顶点到另一个顶点的距离或耗费。这种带权的图称为网。

  3. 邻接点: 对于无向图G,如果图的边(V,V')属于E则称顶点V和V'互为邻接点,即V和V'相邻接。

  4. 度,入度和出度:顶点V的度是指和V相关联的边的数目,记为TD(V)。 对于有向图,顶点V的度分为入度和出度。入度是以顶点V为头的弧的数目,记为ID(v);出度是以顶点V为尾的弧的数目,记为OD(v); 顶点的度为\(TD(V)=ID(V)+OD(V)\),一般地,如果顶点\({V_{i}}\)的度记为TD(\(V_{i}\)),那么一个有n个顶点,e条边的图满足下列关系\(e=1/2*\sum\limits_{i=1}^{n}TD(V_{i})\)

  5. 路径和路径长度:在无向图G中,从顶点V到顶点V'的路径是一个顶点序列,如果G是有向图则路径也是有向的。路径长度是一条路径上经过边或弧的数目。

  6. 回路或环:第一个顶点和最后一个顶点相同的路径称为回路或环。

  7. 简单路径,简单回路或简单环:序列中顶点不重复出现的路径称为简单路径,除了第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路称为简单回路或简单环。

  8. 连通,连通图和连通分量:在无向图G中,如果从顶点V到顶点V'有路径,则称V和V'是连通的,如果对于图中任意两个顶点都是连通的,则称图G是连通图。所谓连通分量,指的是无向图中的极大连通子图。

  9. 极小连通子图:该子图是G的连通子图,在该子图中删除任何一条子图不再连通。

  10. 强连通图和强连通分量:在有向图G中,如果对于每一对的顶点都存在路径则称G是强连通图。在有向图中的极大强连通子图称作有向图的强连通分量。

  11. 连通图的生成树:一个极小连通子图,它含有图中全部顶点,但只有足以构成一棵树的n-1条边,这样的连通子图称为连通图的生成树。 一棵n个顶点的生成树有且仅有n-1条边。生成树包含无向图G所有顶点的极小连通子图。生成树所有顶点均由边连接在一起,但不存在回路的图。

  12. 有向树和生成森林:有一个顶点的入度为0,其余顶点的入度均为1的有向图称为有向图。一个有向图的生成森林是由若干棵有向树组成,含有图中全部顶点,但只有足以构成若干棵不相交的有向树的弧。

  13. 生成森林:对于非连通图,由各个连通分量的生成树的集合。


图的存储结构

图没有顺序存储结构,但可以借助二维数组来表示元素之间的关系,即邻接矩阵表示法,图的链式存储方法:邻接表,十字链表,邻接多重表。

邻接矩阵表示法



\(\color{red}{**有向图和无向图的邻接矩阵的表示方法不同**}\)



其中\(W_{ij}\)为弧上的权值。


  `#define MaxInt 32767     //表示极大值,即无穷
   #define MVNum  100       // 最大顶点数
   typedef char VerTexType;    //假设顶点的数据类型为字符型
   typedef int ArcType;        //假设边的权值类型为整型    
   typedef struct 
   { 
     VerTexType vexs[MVNum];   //顶点表
     ArcType arcs[MVNum][MVNum];   //邻接矩阵
     int vexnum,arcnum;      //图的当前点数和边数
      }AMGraph;`




重点来了,重点是通过无向网稍微的更改变为无向图和有向网

邻接矩阵表示法的优缺点


缺点:①不方便增加和删除顶点。②不便于统计边的数目③空间复杂度高,邻接矩阵表示法的空间复杂度均为\(O(n^2)\)


邻接表

邻接表是图的一种链式存储结构,邻接表中每个单链表的第一个结点存放有关顶点的信息,把这个结点看成链表的表头,其余结点存放有关边的信息,这样邻接表便由两部分组成:表头结点表和边表。
表头结点表: 由所有表头结点以顺序结构的形式存储,以便可以随机访问任一顶点的边链表。表头结点包括数据域(data)和链域(firstarc)两部分,其中数据域用于存储顶点\(V_{i}\)的名称或其他信息;链域用于指向链表中第一个结点。
边表:边链表中边结点包括邻接点域(adjvex),数据域(info),和链域(nextarc)三部分,邻接点域指示与顶点\(V_{i}\)邻接的点在图中的位置;数据域存储和边相关的信息如权值;链域指示与顶点\(V_{i}\)邻接的下一条边的结点。



  `///-----图的邻接表的存储表示-------
     #define MVNum  100     //最大顶点数
     typedef struct ArcNode   //边结点
     { 
      int adjvex;      //该边所指向的顶点的位置
      struct ArcNode *nextarc    //指向下一条边的指针
      OtherInfo info;    //和边相关的信息
 }ArcNode;
 typedef struct VNode     //顶点信息
 {
   VerTexType data;
   ArcNode *firstarc;    //指向第一条依附该顶点的边的指针
  }VNode,AdjList[MVNum];   //AdjList表示邻接表类型
   typedef struct
    { 
     AdjList vertices;
     int vexnum,arcnum;    //图的当前顶点数和边数
   }ALGraph`


十字链表

十字链表是有向图的另一种链式存储结构 在弧结点中有五个域其中尾域(tailvex)头域(headvex)分别指示弧尾和弧头这两个顶点在图中的位置,链域hlink指向弧头相同的下一条弧链域tlink指向弧尾相同的下一条弧info域指向该弧的相关信息。

邻接多重表

邻接多重表是无向图的另一种链式存储结构。mark是标志域可以标记该条边是否被搜所过,ivexjvex为该边依附的两个顶点在图中的位置,ilink指向下一条依附于顶点ivex的边,jlink指向下一条依附于顶点jvex的边,info域指向边和边的相关信息的指针域。


一些废话吧最近刚开学,在家的状态还没有完全调整过来整个人完全不在状态,情绪又上头了 写的不太好大家多担待就这样看吧。。。。。。。。。


深度优先遍历

图的遍历是从图中某一个顶点出发,按照某种方法对图中所有顶点访问且仅仅访问一次。

深度优先遍历(DFS)类似于树的先序遍历,对于一个连通图,深度优先搜索遍历的过程如下
(1)从图中某个顶点V出发,访问V
(2)找出刚访问过的顶点的第一个未被访问的邻接点,访问该顶点。以该顶点为新顶点,重复此步骤,直至刚访问过的顶点没有未被访问的邻接点为止。
(3)返回前一个访问过的且仍有未被访问的邻接点的顶点,找出该顶点的下一个未被访问的邻接点,访问该顶点。
(4)重复步骤(2)(3),直至图中所有顶点都被访问过,搜索结束。



解释一下邻接矩阵表示的无向图深度遍历:假设刚开始的起点为顶点2,辅助数组Visited[i]初始化为0,2为1;则开始选择1进行遍历此时Visited[1]等于0表示未被访问过,则将其置于1,则从1开始依次遍历,本身不能遍历 则于顶点2遍历,顶点2已经访问则访问一下个顶点3,此时顶点3的Visited[3]等于0表示未被访问则将其置于1。则对3进行深度优先遍历,顶点3访问其邻接点1已经访问过了,访问顶点5未被访问将其Visited[5]置于1,则对5进行深度优先遍历,结果是顶点2和顶点3已经访问则回退一直回退到顶点1继续访问顶点四,依照上面步骤依次访问就好。


稠密图适用于在邻接矩阵上进行深度遍历
稀疏图适用于在邻接表上进行深度遍历

时间复杂度

当用邻接矩阵表示图时,查找每个顶点的邻接点的时间复杂度为O(\(n^2\)),其中n为顶点数,当以邻接表做图的存储结构查找邻接点的时间复杂度为O(e),其中e为边数,由此当以邻接表做存储结构,深度优先遍历图的时间复杂度为O(n+e)


广度优先遍历

广度优先遍历(BFS)类似于树的层次遍历过程。


广度优先遍历(邻接表表示的实现广度优先遍历)


广度优先遍历的解释:初始化Visited[i]均为0且表示未被访问,先将0号位置入队,则0号位置一访问置1,0号位置出队访问其邻接点1,2则邻接点1,2置1。将1,2入队然后遍历访问1结点,0结点已经访问则访问3,4邻接点将其置1,1结点出队将3,4结点入队;遍历访问2结点,0结点已经访问则访问5,6邻接点将其置1,2结点出队将5,6结点入队;然后遍历3结点,1结点以及访问则访问7邻接点将其置1,3结点出队将7结点入队;此时所有结点都已经访问,按照顺序依次出队即可。






最小生成树



深度优先生成树和广度优先生成树都是基于深度优先遍历和广度优先遍历。

MST性质(一种贪心算法)

构造最小生成树算法


普里目算法又称为(加点法,在加点过程中不能成环即回路)

克鲁斯卡尔算法实质上是选择出权值最小的边连接即可(注意不要成环)

最短路径


习惯上我们称路径上第一个顶点为源点,最后一个顶点为终点
两种最常见的最短路径问题:一种是求某个源点到其余各顶点的最短路径;另一种是求每一对顶点之间的最短路径。

解决最短路径的常见算法






拓扑排序



关键路径






\(Ve(j)是事件最早开始时间=V(j)的起始结点的最早发生时间+各边的权值中的和的最大值\)
\(Vl(i)是事件最晚开始时间是找权值之差的最小值\)
\(l(i)=e(i)\)时的活动\(a_{i}\)为关键活动。



免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM