图
6.1图的定义
图G由两个集合V和E组成,记为G=(V,E) , 其中V是顶点的有穷非空集合, E是V中顶点偶对的有穷集合,这些顶点偶对称为边。V(G)和E(G)通常分别表示图G的顶点集合和边集合,E(G)可以为空集。若E(G)为空,则图G只有顶点而没有边。
对于图G ,若边集E(G)为有向边的集合,则称该图为有向图 ; 若边集E(G)为无向边的集合, 则称该图为无向图。
在有向图中,顶点对<x, y>是有序的,它称为从顶点 x到顶点 y的一条有向边。因此,<x, y>与<y, x>是不同的两条边。顶点对用一对尖括号括起来,x是有有向边的始点,y是有向边的终点。<x, y>也称作一条弧,则 x为弧尾,y为弧头。
在无向图中,顶点对(x, y)是无序的,它称为与顶点x和顶点y相关联的一条边。这条边没有特定的方向,(x,y)与(y,x)是同一条边。为了有别于有向图,无向图的顶点对用一对圆括号括起来。
6.1.2图的基本术语
- 子图:假设有两个图 G = (V, E)和 G'= (V', E'), 如果V包含V‘且 E包含E’, 则称 G'为 G的子图。
- 无向完全图和有向完全图:对于无向图,若具有 n(n-1)/2 条边,则称为无向完全图。 对于有向图,若具有nn( - l)条弧,则称为有向完全图。
- 稀疏图和稠密图:有很少条边或弧(如 e<nolg2 n) 的图称为稀疏图,反之称为稠密图。
- 权和网:在实际应用中,每条边可以标上具有某种含义的数值,该数值称为该边上的权。这些权可以表示从一个顶点到另一个顶点的距离或耗费 。这种带权的图通常称为网。
- 邻接点:对于无向图 G, 如果图的边 (v, v')属于E, 则称顶点 v 和 v'互为邻接点, 即v和v'相邻接。边(v,v')依附于顶点v和v', 或者说边(v,v')与顶点v和v'相关联。
- 度、入度和出度:顶点v的度是指和v相关联的边的数目,记为TD(v)。对于有向图,顶点v的度分为入度和出度。入度是以顶点v为头的弧的数目,记为ID(v); 出度是以顶点v为尾的弧的数目,记为OD(v)。顶点v的度为TD(v)=ID(v)+OD(v)。
- 路径和路径长度:在无向图G中,从顶点 v 到顶点 v' 的路径是一个顶点序列 (v = vi,0, Vi, 1,...,Vi,m=v'), 其中(vi,j-1,vi,j)属于E, 1<=j<=m。如果G是有向图,则路径也是有向的, 顶点序列应满足<vi,j-1,vi,1>属于E,1<=j<=m。路径长度是一条路径上经过的边或弧的数目。
- 回路或环:第一个顶点和最后一个顶点相同的路径称为回路或环。
- 简单路径、 简单回路或简单环:序列中顶点不重复出现的路径称为简单路径。除了第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路,称为简单回路或简单环 。
- 连通、连通图和连通分量:在无向图 G 中,如果从顶点 v 到顶点 v'有路径,则称 v 和 v' 是连通的。如果对于图中任意两个顶点 Vi 、Vj属于V, Vi 和 Vj都是连通的,则称 G 是连通图。 所谓连通分量, 指的是无向图中的极大连通子图。
- 强连通图和强连通分量:在有向图 G 中,如果对于每一对 vi, vj属于 V,vi不等于vj, 从 vi 到 vj 和 从 vj 到 vi 都存在路径,则称G是强连通图。有向图中的极大强连通子图称作有向图的强连通分量。
- 连通图的生成树: 一个极小连通子图,它含有图中全部顶点,但只有足以构成一 棵树的 n-1 条边,这样的连通子图称为连通图的生成树。
- 有向树和生成森林:有一个顶点的入度为 0, 其余顶点的入度均为 l 的有向图称为有向树。 一 个有向图的生成森林是由若干棵有向树组成,含有图中全部顶点,但只有足以构成若干棵不相交的有向树的弧。
6.2 案例引入
案例 6.1: 六度空间理论。
六度空间理论是一个数学领域的猜想,又称为六度分割理论(SixDegrees ofSeparation)。六 度空间理论是 20 世纪 60 年代由美国的心理学家米格兰姆 (Stanley Milgram) 提出的,理论指出: 你和任何一 个陌生人之间所间隔的人不会超过6个,也就是说,最多通过6个中间人你就能够认识任何一个陌生人。
随着新技术的发展,六度空间理论的应用价值受到了人们的广泛关注,除了前面提到的微 软的人立方搜索,很多领域都运用了六度空间理论,例如 SNS 网站、 BLOG 网站、电子游戏社 区、直销网络等。
6.3 图的类型定义
图是一种数据结构,加上一组基本操作,就构成了抽象数据类型。抽象数据类型图的定义如下:
ADTGraph{
数据对象: V是具有相同特性的数据元素的集合,称为顶点集。
数据关系:
R = {VR}
VR = {<v, w>|v,wEV且P(v,w)<v,w>表示从v到w的弧,谓词P (v, w)定义了弧<v, w>的意义或信息}
基本操作:
CreateGraph(&G,V,VR)
初始条件:V是图的顶点集,VR是图中弧的集合。
操作结果:按V和VR的定义构造图G。
DestroyGraph(&G)
初始条件:图G存在。 操作结果:销毁图G。
Locat eVex(G,u)
初始条件:图G存在,u和G中顶点有相同特征。
操作结果:若G中存在顶点u,则返回该顶点在图中的位置;否则返回其他信息。 GetVex(G,v)
初始条件:图G存在,v是G中某个顶点。 操作结果:返回v的值。
PutVex(&G,v,value);
初始条件:图G存在,v是G中某个顶点。
操作结果:对 v赋值value。
FirstAdjVex(G,v)
初始条件:图G存在,v是G中某个顶点。
操作结果:返回 v的第一 个邻接顶点。若v在G中没有邻接顶点,则返回 “空” NextAdjVex(G,v,w)
初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点。
操作结果:返回v的(相对千w的)下一 个邻接顶点。若w是v的最后一 个邻接 点,则返回 “空” 。
InsertVex(&G,v)
初始条件:图G存在,v和图中顶点有相同特征。
操作结果:在图G中增添新顶点v。
DeleteVex(&G,v)
初始条件:图G存在,v是G中某个顶点。
操作结果:删除 G中顶点v及其相关的弧。
InsertArc(&G,v,w)
初始条件:图G存在,v和w是G中两个顶点。
操作结果:在G中增添弧<v, w>,若G是无向图,则还增添对称弧<w, v>。
DeleteArc(&G,v,w)
初始条件:图G存在,v和w是G中两个顶点。
作结果:在G中删除弧<v, w>,若G是无向图,则还删除对称弧<w, v>。
DFSTraverse(G)
初始条件:图G存在。
操作结果:对图进行深度优先遍历,在遍历过程中对每个顶点访问一次。 BFSTraverse(G)
初始条件:图G存在。
操作结果:对图进行广度优先遍历,在遍历过程中对每个顶点访问一次。
}ADT Graph
6.4图的存储结构
6.4.1邻接矩阵
1.邻接矩阵表示法
用邻接矩阵表示法表示图,除了一个用千存储邻接矩阵的二维数组外, 还需要用一个一维数 组来存储顶点信息。 其形式说明如下:
//-----图的邻接矩阵存储表示-----
#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;
2.采用邻接矩阵表示法创建无向网
-
算法描述
Status CreateUDN(AMGraph &G) {//采用邻接矩阵表示法,创建无向网G cin>>G.vexnum>>G.arcnum; //输人总顶点数,总边数 for(i=O;i<G.vexnum;++i) //依次输入点的信息 cin>>G.vexs[i); for(i=O;i<G.vexnum;++i) //初始化邻接矩阵,边的权值均置为极大值MaxInt for(j=0;j<G.vexnum;++j) G.arcs[i][j]=MaxInt; for(k=O;k<G.arcnum;++k) //构造邻接矩阵 { cin>>vl>>v2>>w; //输人一条边依附的顶点及权值 i=LocateVex(G,vl);j=LocateVex(G,v2); //确定vl和v2在G中的位置,即顶点数组的下标 G.arcs[i) [j)=w; //边<v1, v2>的权值置为w G.arcs[j][i]=G.arcs[i][j]; //置<v1,v2>的对称边<v2, v1>的权值为w } //for return OK; }
6.4.2邻接表
1.邻接表表示法
邻接表(Adjacency List) 是图的一 种链式存储结构。 在邻接表中,对图中每个顶点V; 建立一 个单链表,把与 V;相邻接的顶点放在这个链表中。邻接表中每个单链表的第一个结点存放有关顶点的信息, 把这一结点看成链表的表头, 其余结点存放有关边的信息, 这样邻接表便由两部分组 成:表头结点表和边表。
//- - - - -图的邻接表存储表示- - - - -
#define MVNum 100
typedef struct ArcNode
{
int adjvex;
struct ArcNode * nextarc;
Otherinfo info;
}ArcNode;
typedef struct VNode
{
VerTexType data;
ArcNode *firstarc;
}VNode,AdjList[MVNum];
typedef struct
{
AdjList vertices;
int vexnum,arcnum;
}ALGraph;
2.采用邻接表表示法创建无向图
-
算法描述
Status CreateUDG(ALGraph &G) {//采用邻接表表示法, 创建无向图 G cin>>G.vexnum>>G.arcnum; for(i=O;i<G.vexnum;++i { cin>>G.vertices[i].data; G.vertices[i].firstarc=NULL; } for(k=O;k<G.arcnum;++k) { cin>>c1>>c2; i=LocateVex{G,v1};j=LocateVex{G,v2}; pl=new ArcNode; pl->adjvex= j; pl->nextarc=G.vertices[i].firstarc; G.vertices[i].firstarc=pl; p2=new ArcNode; p2->adjvex=i; p2->nextarc=G.vertices[j].firstarc; G.vertices[j].firstarc=p2; } return OK; }
6.4.3十字链表
有向图的十字链表存储表示的形式说明如下所示:
//- - - - -有向图的十字链表存储表示- - - - -
#define MAX_VERTEX_NUM 20
typedef strut ArcBox
{
int tailvext,headvex;
struct ArcBox *hlink, *tlink;
InfoType *info;
}ArcBox;
typedef struct VexNode
{
VertexType data;
ArcBox *firstin,*firstout;
}VexNode;
typedef struct
{
VexNode xlist[MAX_VERTEX_NUM];
int vexnnm, arcnum;
}OLGraph;
6.4.4 临界多重表
在邻接多重表上,各种基本操作的实现亦和邻接表相似。邻接多重表的类型说明如下:
//- - - - -无向图的邻接多重表存储表示-----
#define MAX_VERTEX_NUM 20
typedef enum{unvisited,visited} Visitlf;
typedef struct EBox
{
Visitlf mark;
int ivex, jvex;
struct EBox *ilink, *jlink;
InfoType *info;
}Ebox;
typedef struct VexBox
{
VertexType data;
EBox *firstedge;
}VexBox;
typedef struct{
VexBox adjmulist[MAX_VERTEX_NUM];
int vexnum, edgenum;
}AMLGraph;

浙公网安备 33010602011771号