一、图的定义
1、图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
2、线性表中把数据元素叫元素,树中将数据元素叫结点,在图中数据元素则称之为顶点。
3、线性表中可以没有数据元素,称为空表;树中可以没有结点,叫做空树;在图结构中,不允许没有顶点,在定义中,若V是顶点的集合,则强调了顶点集合V有穷非空。(注意:此处定义有争议,国内部分教材强调点集非空,但在http://en.wikipedia.org/wiki/Null_graph中提出点集可为空)
4、在图中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边来表示,边集可以是空的。
5、若顶点vi到vj之间的边没有方向,则称这条边为无向边,用无序偶对(vi,vj)来表示。如果图中任意两个顶点之间的边都是无向边,则称该图为无向图。如下图就是一个无向图,由于是无方向的,所以连接顶点A与D的边,既可以表示成无序对(A,D),也可以表示成(D,A)。
6、若从顶点vi到vj之间的边有方向,则称这条边为有向边,也称为弧,用有序偶<vi,vj>来表示,其中vi称为弧尾,vj称为弧头。如果图中任意两个顶点之间的边都是有向边,则称该图为有向图。下图就是一个有向图,其中<A,D>就表示弧,注意不能写成<D,A>。
7、在图中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。下面的两个图都不是简单图。
8、在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。含有n个顶点的无向完全图有n x (n-1) / 2条边。如下图。
9、在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向完全图。含有n个顶点的有向完全图有n x (n-1)条边。如下图。
10、对于具有n个顶点和e条边数的图,无向图0<=e<=n(n-1)/2,有向图0<=e<=n(n-1)。
11、有很少条边或弧的图称为稀疏图,反之称为稠密图。这里的稀疏和稠密都是相对而言的。
12、有些图的边或弧具有与它相关的数字,这种与图的边或弧相关的数叫做权。这种带权的图通常称为网。如下图。
13、假设有两个图G1=(V1,{E1})和G2=(V2,{E2}),如果V2⊆V1且E2⊆E1,则称G2为G1的子图。如下带底纹的图均为左侧无向图与有向图的子图。
二、图的顶点与边间关系
1、对于无向图G=(V,{E}),如果边(v1,v2)∈E,则称顶点v1和v2互为邻接点,即v1和v2相邻接。边(v1,v2)依附于顶点v1和v2,或者说(v1,v2)与顶点v1与v2相关联。顶点v1的度是和v1相关联的边的数目,记为TD(v1)。如下图顶点A与B互为邻接点,顶点A的度是3,各个顶点度的和为3+2+3+2=10,此图的边数是5,发现,边数其实就是各顶点度数和的一半,多出的一半是因为重复两次记数。简记为。
2、对于有向图G=(V,{E}),如果弧<v1,v2>∈E,则称顶点v1邻接到顶点v2,顶点v2邻接自顶点v1。弧<v1,v2>和顶点v1,v2相关联。以顶点v1为头的弧的数目称为v1的入度,记为ID(v1);以v1为尾的弧的数目称为v1的出度,记为OD(v1);顶点v1的度为TD(v1)=ID(v1)+OD(v1)。如下图,顶点A的入度为2,出度为1,所以顶点A的度为2+1=3;此有向图的弧有4条,各顶点的出度和为1+2+1+0=4,各顶点的入度和为2+0+1+1=4,所以得到
3、无向图G=(V,{E})中从顶点v1到顶点v2的路径是一个顶点序列(v1=vi,0,vi,1,......,vi,m=v2),其中(vi,j-1,vi,j)∈E,1≤j≤m。如下图的左图的顶点B到顶点D的四种不同的路径。如果G是有向图,则路径也是有向的,顶点序列应该满足<vi,j-1,vi,j>∈E,1≤j≤m。如下图的右图顶点B到顶点D有两种路径,而顶点A到B就不存在路径。
4、路径的长度是路径上的边或弧的数目。如上图的右图的路径长度分别是2和3。
5、第一个顶点到最后一个顶点相同的路径称为回路或环(路径最终回到起始点)。序列中顶点不重复出现的路径称为简单路径。除了第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路,称为简单回路或简单环。如下图的粗线部分都构成环,左侧的环因第一个顶点和最后一个顶点都是B,而C、D、A没有重复出现,所以是一个简单环。而右侧的环由于顶点C的重复就不是简单环了。
三、连通图相关术语
1、在无向图G中,如果从顶点v1到顶点v2有路径,则称v1和v2是连通的。如果对于图中任意两个顶点vi、vj∈V,vi和vj都是连通的,则称G是连通图。下图的左图是无向非连通图,而右图是无向连通图。
2、无向图中的极大连通子图称为连通分量。强调:
1)要是子图。
2)子图要是连通的。
3)连通子图含有极大顶点数。
4)具有极大顶点数的连通子图包含依附于这些顶点的所有边。 上图中左图虽然不是连通图,但是它有两个连通分量,即上图中的右图和下图中的左图,因为下图中的右图不满足连通子图的极大顶点数,所以不是上图中左图的连通分量。
3、在有向图G中,如果对于每一对vi、vj∈V,vi≠vj,从vi到vj和从vj到vi都存在路径,则称G是强连通图。有向图中的极大强连通子图称做有向图的强连通分量。
4、一个连通图的生成树是一个极小的连通子图,它含有图中全部的n个顶点,但只有足以构成一棵树的n-1条边。如下图的图1不是生成树,当去掉两条构成环的边后,比如图2或图3,就满足n个顶点,n-1条边且连通的定义,图2和图3都是一棵生成树。所以:如果一个图有n个顶点和小于n-1条边,则是非连通图,如果多于n-1条边,则必定构成一个环,因为这条边使得它依附的那两个顶点之间有了第二条路径,比如图2和图3,随便加哪两顶点的边都将构成环。不过有n-1条边并不一定是生成树,比如图4。
5、如果一个有向图恰有一个顶点的入度为0,其余顶点的入度均为1,则是一棵有向树。所谓入度为0其实就相当于树中的根结点,其余顶点入度为1就是说树的非根结点的双亲只有一个。一个有向图的生成森林由若干棵有向树组成,含有图中全部顶点,但只有足以构成若干棵不相交的有向树的弧。如下图所示,其中图1是一个有向图,去掉一些弧后,分解为两棵有向树,如图2和图3,且这两棵有向树就是图1有向图的生成森林。
四、图的存储结构之邻接矩阵
1、从图的逻辑结构定义来看,图上任何一个顶点都可被看成是第一个顶点,任一顶点的邻接点之间也不存在次序关系。如下面的四张图,它们其实是同一个图,只是顶点的位置不同。
2、图的邻接矩阵存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。
3、设图G有n个顶点,则邻接矩阵是一个n x n的方阵,定义为:
无向图邻接矩阵实例,如下图,可以发现无向图的边数组是一个对称矩阵。
有向图邻接矩阵实例,如下图,有向图的边数组就不是对称的了,还可以发现顶点v1的入度正好是第v1列各数之和;而出度即是该行的各数之和。
4、设图G是网图,有n个顶点,则邻接矩阵是一个n x n的方阵,定义如下,其中Wij表示(vi,vj)或<vi,vj>上的权值。∞表示一个计算机允许的、大于所有边上权值的值,即一个不可能的极限值。
有向网图邻接矩阵实例,如下图
5、图的邻接矩阵存储的结构代码如下:
6、建立无向网图的邻接矩阵表示的代码如下,从中可以得到n个顶点和e条边的无向网图的创建,时间复杂度为O(n+n²+e),其中对邻接矩阵Garc的初始化消耗了O(n²)的时间。
7、对于边数相对顶点较少的图,这种结构是存在对存储空间的极大浪费的。如下图。
五、图的存储结构之邻接表
1、 数组与链表相结合的存储方法称为邻接表。邻接表的处理办法:
1)图中顶点用一个一维数组存储(也可以用单链表来存储),对于顶点数组中,每个数据元素还要存储指向第一个邻接点的指针。
2)图中每个顶点vi的所有邻接点构成一个线性表,由于其个数不定,用单链表存储,无向图称为顶点vi的边表,有向图则称为顶点vi作为弧尾的出边表。
2、无向图的邻接表结构图示:其中顶点表的各个结点由data和firstedge两个域表示,data是数据域,存储顶点的信息,firstedge是指针域,指向边表的第一个结点,即此顶点的第一个邻接点;边表结点由adjvex和next两个域组成,adjvex是邻接点域,存储某顶点的邻接点在顶点表中的下标,next则存储指向边表中下一个结点的指针。
3、如下图所示,是有向图的邻接表和逆邻接表,要注意的是有向图由于有方向, 是以顶点为弧尾来存储出边表的,这有利于得到每个顶点的出度。为了便于确定顶点的入度或以顶点为弧头的弧,可以建立一个有向图的逆邻接表,即对每个顶点vi都建立一个链接为vi为弧头的表。
4、对于带权值的网图,可以在出边表结点定义中再增加一个weight的数据域,存储权值信息即可,如下图所示。
5、邻接表结点定义代码如下:
6、无向图的邻接表的创建代码:其中应用了单链表创建中的头插法,对于n个顶点和e条边来说,时间复杂度是O(n+e)。
六、图的存储结构之十字链表
1、对于有向图来说,邻接表是有缺陷的,它解决了出度却不容易了解入度,反之逆邻接表解决了入度却不容易了解出度,把邻接表和逆邻接表整合在一起,即成了有向图的一种存储方法:十字链表。
2、重新定义顶点表结点结构如下图,其中firstin表示入边表头指针,指向该顶点的入边表中第一个结点;firstout表示出边表头指针,指向该顶点的出边表中的第一个结点。
重新定义的边表结点结构如下图,其中tailvex是指弧起点在顶点表的下标,headvex是指弧终点在顶点表中的下标,headlink是指入边表指针域,指向终点相同的下一条边;taillink是指出边表指针域,指向起点相同的下一条边,如果是网,可以再增加一个weight域来存储权值。
3、如下图是十字链表的存储图示,其中实线箭头表示的就是邻接表,而虚线箭头就是此图的逆邻接表的表示。
转载链接:http://blog.csdn.net/cdu09/article/details/8980978