文章中其实有很多图来帮助理解,但是因为外链的原因,我电脑上的图不能直接拉过来,要完整版的可以评论我直接发PDF版本。个人笔记,仅供参考。
图
定义
图 G G G(Graph)由顶点集 V V V(Vertex)和边集 E E E(Edge)组成,记为 G = ( V , E ) G = (V, E) G=(V,E)。
若 V = { v 1 , v 2 , . . . , v n } V = \{v_1, v_2,...,v_n\} V={ v1,v2,...,vn},则用 ∣ V ∣ |V| ∣V∣表示图 G G G中顶点的个数,也称图 G G G的阶, E = { ( u , v ) ∣ u ∈ V , v ∈ V } E = \{(u,v)|u\in V,v\in V\} E={ (u,v)∣u∈V,v∈V},用 ∣ E ∣ |E| ∣E∣表示图 G G G中边的条数。
顶点的度、入度、出度
对于无向图,顶点 v v v的度是指依附于该顶点的边的条数,记为 T D ( v ) TD(v) TD(v)。
对于有向图,入度是以顶点 v v v为终点的有向边的数目,记为 I D ( v ) ID(v) ID(v);
出度是以顶点 v v v为起点的有向边的数目,记为 O D ( v ) OD(v) OD(v);
顶点-顶点的关系描述
· 路径
· 回路——第一个顶点和最后一个顶点相同的路径称为回路或环
· 简单路径——在路径序列中,顶点不重复出现的路径成为简单路径
· 简单回路——除第一个顶点和最后一个顶点外,其余顶点不重复出现的回路成为简单回路
· 路径长度——路径上边的数目(可以有多种结果)
· 点到点的距离——从顶点u出发到顶点v的最短路径若存在,则此路径的长度称为从u到v到距离;若不存在路径,则记该距离位无穷 ( ∞ ) (\infty) (∞)
· 无向图中,若从顶点v到顶点w有路径存在,则称v和w是连通的;一个无向图中任意两个顶点都是连通的则称为连通图
· 有向图中,若从顶点v到顶点w和从顶点w到顶点v之间都有路径,则称这两个顶点是强连通的;一个有向图中任何一对顶点都是强连通的,则称为强连通图
!对于n个顶点的无向图G,若G是连通图,则最少有n-1条边;若G是非连通图,则最多可能有 C n − 1 2 C^2_{n-1} Cn−12条边。
!对于n个顶点的有向图G,若G是强连通图,则最少有n条边(形成回路)
研究图的局部——子图
生成子图是包含了原图的所有顶点。
连通分量
无向图中的极大连通子图称为连通分量。(包含尽可能多的顶点和边)
强连通分量
有向图中的极大强连通子图称为有向图的强连通分量。
生成树
连通图的生成树是包含途中全部顶点的一个极小连通子图。
若图中顶点数为n,则它的生成树含有n-1条边。对生成树而言,若砍去它的一条边,则会变成非连通图,若加上一条边则会形成一个回路。
生成森林
在非连通图中,连通分量的生成树构成了非连通图的生成森林。
几种特殊形态的图
无向完全图 a n d and and 有向完全图
图的存储
邻接矩阵法
#define MaxVertexNum 100
typedef struct{
char Vex[MaxVertexNum];
int Edge[MaxVertexNum][MaxVertexNum];
int vexnum, arcnum;
}MGraph;
带权图
#define MaxVertexNum 100 //顶点数目的最大值
#define INFINITY Max_int //宏定义常量“无穷”
typedef char VertexType; //顶点的数据类型
typedef int EdgeType; //带权图中边上权值的数据类型
typedef struct{
VertexType Vex[MaxVertexNum]; //顶点
EdgeType Edge[MaxVertexNum][MaxVertexNum]; //边的权
int vexnum, arcnum; //图的当前顶点数和弧数
}MGraph;
性能分析
空间复杂度: O ( n 2 ) O(n^2) O(n2)——只和顶点数相关,和实际的边数无关
适合用于存储稠密图
邻接矩阵法的性质
设图G的临界矩阵为***A***,则***A*** n ^n n的元素 A n [ i ] [ j ] A^n[i][j] An[i][j]等于由顶点 i i i到顶点 j j j的长度为 n n n的路径的数目
邻接表
顺序 + 链式存储
十字链表法
只能存储有向图
邻接多重表
图的基本操作
主要考察邻接矩阵和邻接表。
图的遍历
广度优先遍历
分为广度优先遍历(Breadth-First-Search, BFS)和深度优先遍历(Depth-First-Search, DFS)。
bool visited[MAX_VERTEX_NUM]; //访问标记数组
//广度优先遍历
void BFS(Graph G, int v){
//从顶点v出发,广度优先遍历图G
visit(v); //访问初始顶点v
visited[v] = TRUE; //对v做已访问标记
Enqueue(Q, v); //顶点v入队列Q
while(!isEmpty(Q)){
DeQueue(Q, v); //顶点v出队列
for(w=FirstNeighbor(G, v)l w>=0; w=NextNeighbor(G, v, w