C++数据结构之图

图和有向图

图形结构简称为图,属于复杂的非线性结构。元素称为顶点,每个顶点可以有多个或零个前驱顶点,也可以有多个或零个后驱顶点。是多对多的任意关系。这些顶点通过一系列边结对(连接)

  • 图,包括无向图和有向图;网,是指带权的图,包括无向网和有向网。

  • 树和链表可以看成一种特殊的图

图的基本常识

弧头和弧尾

有向图中,无箭头一端的顶点通常被称为"初始点"或"弧尾",箭头直线的顶点被称为"终端点"或"弧头"。

入度和出度

对于有向图中的一个顶点 V 来说,箭头指向 V 的弧的数量为 V 的入度(InDegree,记为 ID(V));箭头远离 V 的弧的数量为 V 的出度(OutDegree,记为OD(V))。拿图 2 中的顶点 V1来说,该顶点的入度为 1,出度为 2(该顶点的度为 3)。

(V1,V2) 和 <V1,V2> 的区别

无向图中描述两顶点(V1 和 V2)之间的关系可以用 (V1,V2) 来表示,而有向图中描述从 V1 到 V2 的"单向"关系用 <V1,V2> 来表示。

图的表示

邻接矩阵

唯一

在邻接矩阵实现中,由行和列都表示顶点,由两个顶点所决定的矩阵对应元素表示这里两个顶点是否相连、如果相连这个值表示的是相连边的权重。例如,如果从顶点A到顶点B有一条权重为 5.6 的边,那么矩阵中第A行第B列的位置的元素值应该是5.6:

邻接表

不唯一

在邻接列表实现中,每一个顶点会存储一个从它这里开始的边的列表。比如,如果顶点A 有一条边到B、C和D,那么A的列表中会有3条边,每一个顶点都有一个链表。

边列表

图的搜索

给定顶点开始遍历

深度优先DFS

1.首先任意找一个未被遍历过的顶点,例如从 V1 开始,由于 V1 率先访问过了,所以,需要标记 V1 的状态为访问过;

2.然后遍历 V1 的邻接点,例如访问 V2 ,并做标记,然后访问 V2 的邻接点,例如 V4 (做标记),然后 V8 ,然后 V5 ;

3.当继续遍历 V5 的邻接点时,根据之前做的标记显示,所有邻接点都被访问过了。此时,从 V5 回退到 V8 ,看 V8 是否有未被访问过的邻接点,如果没有,继续回退到 V4 , V2 , V1 ;

4.通过查看 V1 ,找到一个未被访问过的顶点 V3 ,继续遍历,然后访问 V3 邻接点 V6 ,然后 V7 ;

5.由于 V7 没有未被访问的邻接点,所有回退到 V6 ,继续回退至 V3 ,最后到达 V1 ,发现没有未被访问的;

6.最后一步需要判断是否所有顶点都被访问,如果还有没被访问的,以未被访问的顶点为第一个顶点,继续依照上边的方式进行遍历。

深度优先搜索是一个不断回溯的过程。

  for (list<int>::iterator 
          it = myAdjacencyLists[i].adjacencyList.begin();
          it != myAdjacencyLists[i].adjacencyList.end(); it++)
      out << *it << "  ";
    out << endl;
  }

广度优先

还拿图 1 中的无向图为例,假设 V1 作为起始点,遍历其所有的邻接点 V2 和 V3 ,以 V2 为起始点,访问邻接点 V4 和 V5 ,以 V3 为起始点,访问邻接点 V6 、 V7 ,以 V4 为起始点访问 V8 ,以 V5 为起始点,由于 V5 所有的起始点已经全部被访问,所有直接略过, V6 和 V7 也是如此。 以 V1 为起始点的遍历过程结束后,判断图中是否还有未被访问的点。

广度优先搜索的实现需要借助队列这一特殊数据结构

生成树

对连通图进行遍历,过程中所经过的边和顶点的组合可看做是一棵普通树,通常称为生成树。

连通图中的生成树必须满足以下 2 个条件:

包含连通图中所有的顶点;
任意两顶点之间有且仅有一条通路;

边的数量比顶点数量少一

最小生成树

  • 必须只使用该网络中的边构造最小生成树;
  • 必须使用且仅使用 n-1 条边来联结网络中的 n 个顶点;
  • 不能使用产生回路的边。

普利姆算法

以点为出发点

某顶点 u0 出发,选择与它关联的具有最小权值的边(u0, v),将其顶点加入到生成树的顶点集合U中

克鲁斯卡尔算法

以边为出发点

在 E 中选到一条具有最小权值的边,若该边的两个顶点落在不同的连通分量上(即不形成回路),则将此边加入到 T 中;

生成森林

生成树是对应连通图来说,而生成森林是对应非连通图来说的。

我们知道,非连通图可分解为多个连通分量,而每个连通分量又各自对应多个生成树(至少是 1 棵),因此与整个非连通图相对应的,是由多棵生成树组成的生成森林。

存储结构

数组

    存储图中各顶点本身数据,使用一维数组就足够了;存储顶点之间的关系时,要记录每个顶点和其它所有顶点之间的关系,所以需要使用二维数组(邻接矩阵)。

链表

邻接表

    邻接表存储图的实现方式是,给图中的各个顶点独自建立一个链表,用节点存储该顶点,用链表中其他节点存储各自的临界点。

活动网络AOV

    **有向图**表示一个工程。用顶点表示事件,用有向边<Vi, Vj>表示活动。Vi 必须先于活动Vj 进行。这种有向图叫做AOV网络。入度为0的顶点称为**源点**,出度为0的顶点称为**汇点**

  • 对给定的AOV网络,必须先判断它是否存在有向环。
    • 检测有向环的一种方法,是对AOV网络构造其拓扑有序序列。将各个顶点 排成一个线性有序的序列,使得AOV网络中所有应存在的前驱和后继关系都能得到满足。

关键路径:从源点到汇点的最长路径的长度,下图中的:1-2-5-7-9 即为一条关键路径,权值的和为18。

最短路径

[​​​​​​【图】最短路径--迪杰斯特拉(Dijkdtra)算法_菜鸟成长记-优快云博客_最短路径

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值