目录
一、图的定义和基本术语
1、图:G=(V,E)
V:顶点(数据元素)的有穷非空集合;
E:边的有穷集合。
2、无向图:每条边都是无方向的
3、有向图:每条边都是有方向的
4、完全图:任意两个点都有一条边相连
(1)无向完全图:n个顶点,n(n-1)/2条边
(2)有向完全图:n个顶点,n(n-1)条边
5、稀疏图:有很少边或弧的图(e<nlogn)
6、稠密图:有较多边或弧的图
7、网:边、弧带权的图
8、邻接:有边、弧相连的两个顶点之间的关系。
存在(vi,vj),则称vi和vj互为邻接点,存在(vi,vj),则称vi和vj互为邻接点;
存在<Vi, Vj>,则称vi邻接到vj,vj邻接于vi。
9、顶点的度:与该顶点相关联的边的数目,记为TD(v)
在有向图中,顶点的度等于该顶点的入度与出度之和。
顶点v的入度是以v为终点的有向边的条数,记作 ID(v)
顶点v的出度是以v为始点的有向边的条数,记作 OD(V)
10、路径与回路
(1)路径:接续的边构成的顶点序列。
(2)路径长度:路径上边或弧的数目/权值之和。
(3)回路(环):第一个顶点和最后一个顶点相同的路径。
(4)简单路径:除路径起点和终点可以相同外,其余顶点均不相同的路径。
(5)简单回路(简单环):除路径起点和终点相同外,其余顶点均不相同的路径。
11、连通图〔强连通图)
在无(有)向图G=( V. {E})中,若对任何两个顶点v、u都存在从v到u的路径,则称G是连通图(强连通图)。
12、权与网
图中边或弧所具有的相关数称为权。表明从一个顶点到另一个顶点的距离或耗费。
带权的图称为网。
二、图的类型定义
1、图的抽象数据类型定义如下:
ADT Graph{
数据对象V:具有相同特性的数据元素的集合,称为顶点集。
数据关系R: R={VR}
vR={<v,w>|<v,w>| v,w属于V ~ p(v,w),
<v,w>表示从v到w的弧,P(v,w)定义了弧<v,w>的信息)}
2、基本操作p
Create_Graph():图的创建操作。
初始条件:无。
操作结果:生成一个没有顶点的空图G。
GetVex(G,v):求图中的顶点v的值。
初始条件:图G存在,v是图中的一个顶点。
操作结果:生成一个没有顶点的空图G。
CreateGraph(&G.V,VR)
初始条件:V是图的顶点集,VR是图中弧的集合。
操作结果:按V和VR的定义构造图G。
DFSTraverse(G)
初始条件:图G存在。
操作结果:对图进行深度优先遍历。
BFSTraverse(G)
初始条件:图G存在。
操作结果:对图进行广度优先遍历。
}ADT Graph
三、图的存储结构
图的存储结构主要有邻接矩阵和邻接表两种
1、邻接矩阵
(1)优点:容易实现图的操作如:求某顶点的度、判断顶点之间是否有边(弧)、找顶点的邻接点等。
(2)缺点:邻接矩阵缺点,n个顶点需要n*n个单元存储边(弧);空间效率为O(n^2)
#define MaxVNum 100
typedef enum {DG,UDG,DN,UDN} GrapgKind;
typedef struct{
int adj;
char *info;
}Edge,AdjMatrix[MaxVNum][MaxVNum];
typedef struct{
char *vexs[MaxVNum];
AdjMatrix edges;
int vexNum,edgeNum;
GraphKind kind;
}MGraph;
2、邻接表
(1)当图所含边的数目较小时,采用邻接矩阵会浪费很多空间
(2)对图中的每个顶点都建立一个单链表,第i个单链表包含所有与顶点i邻接的边。
四、图的深度优先搜索与广度优先搜索
1、图的深度优先搜索(DFS)
int visited[MaxVertNum]={0};
void dfs(AMGraph G,int v){
printf("%s",G.verts[v]);
visited[v]=1;
for(int w=firstAdjVert(G,v);w>=0;w=nextAdiVert(G,v,w))
if(!visited[w])
dfs(G,w);
void DFS(AMGraph G){
for(int v=0;v<G.vertNum;v++)
if(!visited[v])
if(!visited[v])
dfs(G,v);
}
}
2、图的广度优先搜索
void BFSTraverse(Graph G){
for(v=0;v<G.vexNum;++v)
visited[v]=FALSE;
InitQueue(&Q);
for(v=0;v<G.vexNum;++v){
if(!visited[v]){
visited[v]=TRUE;visit(v);
EnQueue(&Q,v);
while(!QueueEmpty(Q)){
DeQueue(&Q,u);
for(w=FirstAdjVex(G,u);w>=0;;w=NextAdjVex(G,u,w))
if(!visited[w]){
visited[w]=TRUE;
visit(w);EnQueue(&Q,w);
}
}
}
}
}