图的基础学习

一、图的结构


树和图一样,也是一种非线性结构,线性结构中的数据元素之间是“一对一”的关系,树形结构中的数据元素之间是“一对多”的关系,而图中的数据元素之间是“多对多”的关系,每个数据元素可以有多个直接前驱和多个直接后继,即图的结构是网状结构。
注:图与线性表、树不一样,线性表、树可以为空表、空树,但图不能为空图。

二、图的定义


无论多么复杂的图都是由顶点和边构成的,采用形式化的定义,图G(Graph)由两个集合V(Vertex)和E(Edge)组成,记为G=(V,E),其中V是顶点的有限集合,记为V(G),E是连接V中两个不同顶点(顶点对)的边的有限集合,记为E(G),对于含有n个顶点的图,通常用字母或自然数来唯一标识图中顶点(顶点的编号)

(一)有向图和无向图

按照图中的边是否有方向性,可以分为有向图和无向图。

1、无向图和无向完全图

无向图中每条边都没有方向,一般用圆括号“()”表示两个顶点之间的,若边中带有数据信息,则称为,(vi,vj)表示顶点vi和顶点vj之间的无向边。【带权的无向图称为无向网】

 

 上图可表示为:
G=(V,E)
V= {V1,V2,V3,V4}
E= {(V1,V2),(V1,V3),(V2,V1),(V2,V3),(V2,V4),(V3,V4)}

若一个无向图中,若每个顶点都有一条边连接,则称为无向完全图,可知:

在一个含有n个顶点的无向完全图中,共有n(n-1)/2条边。

例如,下面就是一个无向完全图,n=4,含有6条边:

2、有向图和有向完全图
有向图中每条边都有方向,一般用尖括号“<>”表示两个顶点之间的首尾关系,<vi,vj>表示从顶点vi到顶点vj的弧,同样,若弧中带有数据信息,也称为权。<vi,vj>其中第一项vi称为弧尾,第二项vj称为弧头,也称为顶点vi邻接到顶点vj。【带权的有向图称为有向网】

 

上图可表示为:
G=(V,E)
V= {V1,V2,V3,V4}
E= { <V2,V1>,<V2,V3>,<V2,V4>,<V3,V1>,<V4,V3> } 

若一个有向图中,若每个顶点都有互相相反的两条弧连接,则称为有向完全图,可知:

在一个含有n个顶点的有向完全图中,共有n(n-1)条弧。

例如,下面就是一个有向完全图,n=4,含有12条弧,每个顶点都有相互的弧连接:

(二)度的概念

1、无向图的度

对于无向图G= (V, E), 如果边(v,v’)属于E, 则称顶点v和v‘互为邻接点,即(v,v’)与顶点v和v’相关联。顶点v的度是和v相关联的边的数目。如下面这个无向图,顶点A 的度为3。各个顶点度的和=3+2+3+2=10。而此图的边数是5,推敲后发现,边数其实就是各顶点度数和的一半,多出的一半是因为重复两次计数。

2. 有向图

顾名思义,有向图就是图上的边有方向。下图就是一个有向图。该图的顶点集为 V = { A , B , C , D } ,边集 E = { < B , A > , < B , C > , < C , A > , < A , D > }。在有向图中,边 < u , v >和边 < v , u >是不一样的。通常情况下,有向图中的边用< >表示,无向图中的边用( )表示。


对于有向图G = (V, E),如果边<v,v’>属于E,则称顶点v邻接到顶点v’,顶点v’邻接自顶点v的边<v,v’>和顶点v, v’相关联。
从顶点v出发的边的数目称为v的出度;到达顶点v的边的数目称为v的入度,顶点v的度=出度+入度。以上面这个有向图为例,
顶点A的入度是2 (从B到A的边,从C到A的边),出度是1(从A到D的边),所以顶点A的度为2+1=3。此有向图的边有4 条,而各顶点的出度和为1+2+1+0=4,各顶点的入度和=2+0+1+1=4。

 

   5)邻接

  ①若无向图中的两个顶点V1和V2存在一条边(V1,V2),则称顶点V1和V2邻接(Adjacent);

  ②若有向图中存在一条边<V3,V2>,则称顶点V3与顶点V2邻接,且是V3邻接到V2或V2邻接直V3

PS:无向图中的边使用小括号“()”表示,而有向图中的边使用尖括号“<>”表示。

 6)路径

在无向图中,若从顶点Vi出发有一组边可到达顶点Vj,则称顶点Vi到顶点Vj的顶点序列为从顶点Vi到顶点Vj的路径(Path)。

 7)连通

  若从Vi到Vj有路径可通,则称顶点Vi和顶点Vj是连通(Connected)的。

 8)权

有些图的边或弧具有与它相关的数字,这种与图的边或弧相关的数叫做权(Weight)。有些图的边或弧具有与它相关的数字,这种与图的边或弧相关的数叫做权(Weight)。

 

 
三、图的存储结构


1. 邻接矩阵


图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组来表示图。一个一维数组存储图中顶点的信息,一个二维数组(称为邻接矩阵)存储图中边的信息。
(1)下图是使用邻接矩阵存储无向图。如图所示,设置两个数组,顶点数组为vertex[4] = {v0, v1, v2, v3},边数组arc[4][4]实际上是一个矩阵。对于矩阵的主对角线的值,即arc[0][0]、arc[1][1]、arc[2][2]、arc[3][3]全为0,这是因为顶点上不存在自环的边。通过这个例子可以看出,无向图的邻接矩阵是一个对称矩阵。

(2)下图是使用邻接矩阵存储有向图。如图所示,设置两个数组,顶点数组为vertex[4] = {v0, v1, v2, v3},边数组arc[4][4]实际上是一个矩阵。对于矩阵的主对角线的值,即arc[0][0]、arc[1][1]、arc[2][2]、arc[3][3]全为0,这是因为顶点上不存在自环的边。通过这个例子可以看出,有向图的邻接矩阵并不是一个对称矩阵。

不足:由于存在n个顶点的图需要n*n个数组元素进行存储,当图为稀疏图时,使用邻接矩阵存储方法将会出现大量0元素,这会造成极大的空间浪费。这时,可以考虑使用邻接表表示法来存储图中的数据。

2.2 邻接表表示法

  首先,回忆我们在线性表时谈到,顺序存储结构就存在预先分配内存可能造成存储空间浪费的问题,于是引出了链式存储的结构。同样的,我们也可以考虑对边或弧使用链式存储的方式来避免空间浪费的问题。

  邻接表由表头节点表节点两部分组成,图中每个顶点均对应一个存储在数组中的表头节点。如果这个表头节点所对应的顶点存在邻接节点,则把邻接节点依次存放于表头节点所指向的单向链表中。

  (1)无向图:下图所示的就是一个无向图的邻接表结构。

从上图中我们知道,顶点表的各个结点由data和firstedge两个域表示,data是数据域,存储顶点的信息,firstedge是指针域,指向边表的第一个结点,即此顶点的第一个邻接点。边表结点由adjvex和next两个域组成。adjvex是邻接点域,存储某顶点的邻接点在顶点表中的下标,next则存储指向边表中下一个结点的指针。例如:v1顶点与v0、v2互为邻接点,则在v1的边表中,adjvex分别为v0的0和v2的2。

PS:对于无向图来说,使用邻接表进行存储也会出现数据冗余的现象。例如上图中,顶点V0所指向的链表中存在一个指向顶点V3的同事,顶点V3所指向的链表中也会存在一个指向V0的顶点。

  (2)有向图:若是有向图,邻接表结构是类似的,但要注意的是有向图由于有方向的。因此,有向图的邻接表分为出边表和入边表(又称逆邻接表),出边表的表节点存放的是从表头节点出发的有向边所指的尾节点;入边表的表节点存放的则是指向表头节点的某个顶点,如下图所示。

 

(3)带权图:对于带权值的网图,可以在边表结点定义中再增加一个weight的数据域,存储权值信息即可,如下图所示。

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值