数据库图

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

V0
V1
V1
V3
V3
V2
无向图 G1
V0
V2
有向图G2
3
2.图的相关概念
V0
V1 V1
V3
顶点(或结点):图中,
数据元素vi称为顶点 (vertex )或结点。
V3
V2 V0
V2
无向图:图中,如果某两个顶点构成的(vi, vj)∈E 是无序偶,即顶点之间的连线是没有方向区分的,则 称这样的边是无向边,简称边。用(vi, vj)来表示, 称vi和vj互为邻接点。如果某图全部是由无向边构成, 则称该图为无向图。
int n,e;
/*顶点数和边数*/
}Mgragh;
【算法7.1】图邻接矩阵的存储实现
void CreateMGraph(Mgragh *G)
int i,j,k,w; char ch; printf("请输入顶点数和边数:\n"); scanf("%d,%d",&(G->n),&(G->e)); /*输入*/ printf("请输入顶点信息:\n");
7.2.1 邻接矩阵
用二维数组来描述图中结点之间相邻关系的存储
结构。假设有图G=(V,E),其中V={v0,v1,…,vn-1}, 用一个n×n的矩阵来表示G中各顶点相邻的关系,则
矩阵的表示如下:
1 若(vi, vj)或者 vi, vj E(G)
A[i][ j] 0
否则
V0
V2
0 1 0 0
13
for (i=0;i<G->n;i++) scanf("%c",&(G->vexs[i])); for (i=0;i<G->n;i++)
for (j=0;j<G->n;j++) G->adj[i][j]=0; /*初始化邻接矩阵*/
printf("输入每条边对应的两个顶点的序号:\n"); for (k=0;k<G->e;k++)
7.1 图的基本概念 7.2 图的存储表示 7.3 图的遍历 7.4 图的生成树 7.5 最短路径 7.6 拓扑排序 7.7 关键路径
小结
1
本章主要内容
《数据结构》主要包括三种基本结构:线性结构,树型结 构,图型结构。本章将学习图型结构知识。在图结构中, 每个结点都可以和其它任何结点相连接。通过本章内容学 习,应该掌握的知识如下:
V1
3
V3
A

1

0 0
0 1 1
1 0 1
1
1 0

11
邻接矩阵的说明: ① 无向图的邻接矩阵是一个对称矩阵。 ② 无向图邻接矩阵第i行(或第i列)中非零元素的个数 表示第i个顶点的度。 ③ 有向图邻接矩阵第i行(或第i列)中非零元素的个数 表示第i个顶点的出度(或入度)。 ④ 用邻接矩阵方法存储图,很容易确定图中任意两个 顶点之间的邻接关系。
对于无向图,其中任意两顶点都是连通的,则称 该无向图是连通图。无向图中的极大连通子图称为连 通分量。
V0
V2
V0
V4
V2
V4
V3
V5
V1
V3
V1
V5
无向图G3及连通分量
9
在有向图中,若任意两个顶点vi和vj都连通,则称该有向 图为强连通图。有向图的极大强连通子图称为强连通分量。
V0
V1
V1
V0
V2
V3
V2
目满足如下关系:
V1
V3
n
2e=( ∑ i=1
D(vi))
V0
V2
6
网络:若图的每条边(弧)都被赋予了具体含义,
这种与图的边(弧) 相关的数据称为权,称这样的图为
加权图或网络。
路径:在无向图中,若存在一个顶点序列
vi,vi1,vi2,…,vim,vj,使得(vi,vi1),(vi1,vi2),…,
printf("%c",G.adjlist[i].vertex); visited[i]=1; p=G.adjlist[i].firstedge; while(p!=NULL) {if(visited[p->adjvex]==0) DFSTraverseAL(G,p->adjvex); p=p->next; } }
{scanf("%d,%d",&i,&j); /*输入e条边*/ G->adj[i][j]=1; } /*若加入G->adj[j][i]=1;则 为无向图的邻接矩阵存储建立*/ }/*CreateMGraph*/
14
7.2.2 邻接表
邻接表是图的顺序与链式相结合的存储方法.
邻接表的存储思路:对图中的每个顶点建立一个单链表,第
2.图的邻接矩阵的建立
图的邻接矩阵存储方法用一个二维数组存储顶点之间 的相邻关系,再用一个一维数组存储顶点信息,另外 还需要存储图的顶点数和边(弧)数。
12
typedef char Vextype;
typedef struct {
Vextype vexs[VEX_NUM];
int adj[MAXSIZE][MAXSIZE]; /*邻接矩阵*/
(vim,vj)均属于E(G),则称顶点vi到vj 存在一条路径。
对于有向图,路径由弧组成,
即<vi,vi1>,<vi1,vi2>,…,<vim,vj>
4 V0
V2
均属于E(G)。
7 5
6
路径上边的数目称为路径长度。 V1 2
V3
无向加权图
7
回路:假设从vi到vj存在一条路径,且vi=vj,则 称该路径为回路。顶点不重复出现的路径称为简单 路径。
的边的数目,通常记为D (v)。
在有向图中,将从该顶点出发的弧的数目称为该
顶点的出度,用OD(v)表示;对应的,将以该顶点结
束的弧的数目称为该顶点的入度,用ID(v)表示;有
向图顶点的度为出度和入度之和: V0
V1
D (v)=ID (v)+OD(v)。
结论:对于具有n个顶点、e条边
的图,顶点vi的度D (vi)与边的数
边结点
EdgeNode *firstedge; }VertexNode;
vertex firstedge
typedef struct
表头结点
{ VertexNode adjLeabharlann Baiduist[MAXSIZE];
int n,e;
} ALGraph;
16
V0
V2
V1
3
V3
0 V0
1 V1
1∧
0
2
2 V2
1
3∧
3 V3
有向图:在一个图中,如果两个顶点构成的<vi, vj>∈E是序偶,则称这样的边是有向边,简称弧。用 <vi, vj>来表示。如果某图全部是由有向边构成,则称 该图为有向图。
4
无向完全图:在一个无向图中,设V是包含n个结
点的集合,且对于任意两个不相同的顶点之间都有
一条边将它们连接,则称该图为无向完全图。
子图:设G(V,E),G’(V’,E’)是两个图,假设 V’⊆V且E’⊆E,称G’为G的子图。当满足V’=V 且E’⊆E,称G’为G的生成子图。
V0
V1 V1
V3 V0
V1 V1
V3
V2
无向图 G1
V0
V2
有向图G2
V3
V2 V0
V2
图G1和G2的子图
8
连通、强连通 若从顶点vi到顶点vj(i≠j)之间有路径 存在,则称该两个顶点是连通的。
void DFSTraverseM(MGraph *G,int i) /*从i结点开始深度优先遍历以邻接矩阵存储的图G*/
{ printf("%c",G->vexs[i]);
visited[i]=1;
/*标志向量初始化*/
for (j=0;j<G->n;j++)
if ((G->adj[i][j]==1)&&(!visited[j]))
V0
V2
V1
V3
V4 V5
V6
V7 无向图
最终得到的顶点访问序列为: v0 →v1 →v6→v5→v4→v2→v3→v7。
在遍历结点的过程中需要一个访问标志数组 visited[],用来记录被访问过的顶点。
21
【算法7.3】采用邻接矩阵存储的图的深度优先遍历
int visited[VEX_NUM]={0};
18
假设无向图中有n 个顶点、e条边, 则它的邻接表需n个头结点和2e个边 结点。显然,在边数很少(e<<n(n1)/2)的情况下,用邻接表表示图比 邻接矩阵节省存储空间。
图的逆邻接表
V1
V3
V0
V2
有向图G2
0 V0 ∧ 1 V1 2 V2 3 V3 ∧
0 1∧
(a) 邻接表
3∧
0 V0
1 V1 2 V2 ∧ 3 V3
1∧ 2∧
1∧
(b) 逆邻接表
19
7.3 图的遍历——从图中的某个顶点出发,对图中所 有顶点访问且只访问一次的过程。有深度优先遍历和 广度优先遍历两种方式。
7.3.1 深度优先遍历(DFS)
从图中某个顶点v出发,找一个与v相邻接且没有
被访问过的顶点w访问,然后从w开始进行深度优先
遍历。此过程依此类推,直到所有顶点全部被访问为
15
用邻接表表示的形式描述如下:
typedef struct node
/*边结点*/
{ int adjvex;
/*邻接点域*/
struct node * next; /*指向下一个边结点的指针域*/
}EdgeNode; typedef struct vnode
adjvex next
{ Vextype vertex;
V3
有向图G4
V2
V3
G4的强连通分量
生成树:连通图G的生成树,是G中包含其全部n个顶点的一 个极小连通子图。即由n个顶点,n-1条边构成的连通图。 生成森林:在非连通图中,由每个连通分量都可得到一个极小 连通子图,即一棵生成树。这些连通分量的生成树就组成了一 个非连通图的生成森林。
10
7.2 图的存储表示——邻接矩阵、邻接表等
i个单链表中的结点表示和顶点vi相连接的顶点,称为边结点。
每个边结点包括两个域,其中邻接点域(adjvex)存储与顶点 vi邻接的顶点在图中的位置(或序号),指针域(next)用来指向 下一条边(或弧)的结点.
vertex firstedge
表头结点
adjvex next
边结点
每个链表依附于一个表头结点:链域(firstedge)指向链表中 的第一个结点,顶点域(vertex) 存储顶点vi有关信息.
23
图的定义和相关术语 图的存储 图的遍历 最小生成树 拓扑排序 最短路径 关键路径
2
7.1 图的基本概念 1.图的定义
图G (Graph)是由非空的顶点集合V(G)和描述顶点 之间关系的边集合E(G)构成,其形式定义为:G =(V(G),E(G))。简写为G=(V,E)。 G表示一个图,V是图G中非空顶点的集合,E是图G 中边的集合。
DFSTraverseM(G,j); /*vj未访问,从vj开始DFS搜索*/ }/*DFSTraveseM*/
22
【算法7.4】采用邻接表存储的图的深度优先遍历 int visited[VEX_NUM]={0}; void DFSTraverseAL(ALGraph G,int i) {EdgeNode *p;
结论:在一个含有n个顶点的无向完全图中,有n(n-
1)/2条边。
有向完全图:在一个有向图中,设V是包含n个结
点的集合,且对任意两个不同结点之间都有方向相
反的两条弧相连,则称该图为有向完全图。
结论:在一个含有n个顶点的有向完全图中,有
n(n-1)条弧。
V0
V1
V1
V3
V3
V2
V0
V2
5
顶点的度:顶点的度(degree)是指和该顶点相关联
止。
V0
以无向图为例,深度优先
V2
V1
遍历过程如下:
(1) 从顶点v0出发进行遍历, V3 V4 V5 V6
在访问了顶点v0之后,选择 其邻接点之一v1访问。
V7 无向图
20
(2) 从v1出发进行遍历。可选 择点有v6和v0,由于v0已经被 访问过,因此选择v6。 (3) 从v6出发进行遍历。可选 择点有v1和v5,由于v1已被访 问过,选择v5。
{ scanf("%d,%d",&i,&j); s=(EdgeNode*)malloc(sizeof(EdgeNode)); s->adjvex=j; s->next=G->adjlist[i].firstedge; G->adjlist[i].firstedge=s; } }/*CreateALGraph*/
1
2∧
【算法7.2】建立有向图的邻接表存储 void CreateALGraph(ALGraph *G) { /*建立有向图的邻接表存储*/
int i,j,k; EdgeNode * s;
3∧
17
printf(“请输入顶点数和边数:\n”); scanf(“%d,%d”,&(G->n),&(G->e)); printf(“请输入顶点信息:\n”); for (i=0;i<G->n;i++) { scanf(“%c”,&(G->adjlist[i].vertex)); G->adjlist[i].firstedge=NULL; } printf("请输入边的信息:\n"); for (k=0;k<G->e;k++) /*建立边表*/
相关文档
最新文档