-
有向图:弧室定点的有序对 <v,w>
-
无向图:无向边的有限集合
-
简单图:
- 不存在重复边
- 没有到自己的边
-
完全图:
- n个顶点,无向完全图有n(n-1)/2条边
- 有向完全图n(n-1)条边
-
连通
- 在无向图中,若v到w有路径存在,v和w是连通的。若图G中任意两个顶点时连通的,则是连通图
- 极大连通子图是无向图的连通分量,要求包含所有的边。
- 极小连通子图是连通的但边最少。
-
强连通
- 在有向图中,从顶点v到w相互有路径,这两个点强连通
- 任何一对顶点都强连通->强连通图
-
生成树和生成森林
- 连通图的生成树是包含全部顶点的极小连通子图
- 若有n个顶点,就是在生成树中有n-1条边
- 当砍一条边就变成非连通,加上一条边可以形成回路
- 在非连通图中,连通分量的生成树构成了非连通图的生成森林
-
顶点的度/入度/出度
- 无向图中只有度:度是边数的2被
- 入度:以顶点v为终点
-
边的权和网
- 边上有权值的图:网
- 当|E| < |v|log|v|的时候,G为稀疏图
-
路径和路径长度
- 顶点Vp到顶点Vq之间的一条路径是顶点Vp,Vi,Vj...Vq
- 路径上边的数目是路径长度
-
简单路径/简单回路
- 简单路径:顶点不重复出现的路径
- 简单回路:除了首尾顶点,其余顶点不重复
-
距离
- u到v最短路径若存在,就是u到v的距离
-
邻接矩阵法
-
#define MaxVertexNum 100 typedef char VertexType; //顶点 typedef int EdgeType; //边上权值 typedef struct { VertexType Vex[MaxVertexNum]; //顶点表 EdgeType Edge[MaxvertexNum][MaxvertexNum]; //邻接矩阵 int vexnum,arcnum; //顶点and弧数 }MGraph;
-
-
邻接表法
-
特点
- 无向图,存储空间O(|V|+2|E|)
- 有向图,存储空间O(|V|+|E|)
- 稀疏图,邻接表可以节省大量空间
-
#define MaxVertexNum 100 typedef struct ArcNode { //边表 int adjvex; //弧指向的顶点的位置 struct ArcNode *next; //指向下一条弧的指针 }ArcNode; typedef struct VNode { //顶点表 VertexType data; ArcNode *first; //指向第一条依附该顶点的弧 }VNode,Adjlist[MaxVertexNum]; typedef struct { AdjList vertices; // 邻接表 int vexnum,arcnum; //图的顶点和弧 }ALGraph;
-
-
十字链表
1.tailvex和headvex分别指示弧尾和弧头这两个顶点在图中的位置。hlink指向弧头相同的下一条弧,tlink指向弧尾相同的下一条弧。
2.顶点结点中,data放顶点相关的数据信息,firstin和firstout分别指向该顶点为弧头或弧尾的第一个弧结点。
3.图的十字链表
#define MaxVertexNum 100
typedef struct ArcNode //边表结点
{
int tailvex,headvex; //弧的头尾结点
struct ArcNode *hlink,*tlink; //指向弧头相同和弧尾相同的结点
}ArcNode;
typedef struct VNode
{//顶点表结点
VertexType data;
ArcNode *firstin, *firstout; //指向第一条入弧和出弧
}VNode;
typedef struct
{
VNode xlist[MaxVertexNum]; //邻接表
int vexnum,arcnum; // 图的顶点数和弧数
}GLGraph;
4.既容易找到vi为尾的弧,又容易找到vi为头的弧,所以容易求得顶点的出度和入度。
- 邻接多重表
- 是无向图的一种链式存储结构
- 在邻接表中,容易求得顶点和边的各种信息,但是邻接表中求两个顶点之间是否存在边而对边执行删除等操作时,需要分别在两个顶点的边表中遍历,效率低。
- 每条边也用一个结点表示,mark标记该边是否被搜过,ivex和jvex为该边依附的两个顶点在图中的位置。ilink指向下一条依附于顶点ivex的边,jlink指向下一条依附于顶点jvex的边。
- data域存储该顶点信息,firstedge域指示第一条依附于该顶点的边。
#defin MaxVertexNum 100
typedef struct ArcNode
{ //边表结点
bool mark; //访问标记
int ivex,jvex; //分别指向该弧的两个结点
struct ArcNode *ilink,*jlink; //分别指向两个顶点的下一条边
}ArcNode;
typedef struct VNode
{//顶点表结点
VertexType data;//顶点信息
ArcNode *firstedge;//指向第一条依附该顶点的边
}VNode;
typedef struct
{
VNode adjmulist[MaxVertexNum];//邻接表
int vexnum,arcnum;//图的顶点数和弧数
}AMLGraph;
-
广度优先搜索:是一种分层的查找过程
-
bool visited[MAX_VERTEX_NUM]; //访问标记数组 void BFSTraverse(Graph G) { for(int i = 0; i < G.vexnum; ++i) visited[i] = FALSE; //访问标记数组初始化 InitQueue(Q); //初始化辅助队列Q for(int i = 0; i < G.vexnum; ++i) //从0号顶点开始遍历 if(!visited[i]) //对每个连通分量调用一次BFS BFS(G,i); } void BFS(Graph G, int v) { visit(v);//访问初始顶点v visited[v] = TRUE;//对v做已访问标记 Enqueue(Q,v);//顶点v入队 while(!isEmpty(Q)) { Dequeue(Q,v);//顶点v出队 for(w = FirstNeighbor(G,v); w >= 0; w = NextNeighbor(G,v,w)) {//检测v所有邻接点 if(!visited[w])//w为v尚未访问的邻接顶点 { visit(w); visited[w] = TRUE; EnQueue(Q,w); } } } }
-
广度优先搜索和二叉树的层次遍历是完全一致的
-
时间复杂度
- 采用邻接表时O(|V|+|E|)
- 采用邻接矩阵O(|V|^2)
-
广度优先生成树
- 邻接矩阵的存储表示唯一,所以生成树唯一
- 邻接表的存储表示不唯一,所以生成树不唯一
-
-
深度优先:类似于树的先序遍历
-
bool visited[MAX_VERTEX_NUM]; void DFSTraverse(Graph G) { for(int v = 0;v < G.vexnum; ++v) visited[v] = FALSE; for(int v = 0;v < G.vexnum; ++v) if(!visited[v]) DFS(G,v); } void DFS(Graph G,int v) { visit(v); visited[v] = TRUE; for(w = FirstNeighbor(G,v); w>= 0; w = NextNeighor(G,v,w)) if(!visited[w]) { DFS(G,w); } }
-
时间复杂度
- 邻接矩阵,O(|V|^2)
- 邻接表,O(|V|+|E|)
-
深度优先的生成树
- 对连通图调用DFS才能产生深度优先生成树,否则深度优先生成森林
- 对于邻接表处处的深度优先生成树是不唯一的
-
-
最小生成树:是图的极小连通子图,包含了所有顶点和尽可能少的边。
- 若砍去他的一条边就会变成非连通图。
- 若增加一条就会形成回路
- 最小生成树不是唯一的,但是各边权值不同时,最小生成树是唯一的,。
- 最小生成树的边的权值之和是惟一的
- 最小生成树的边数为顶点数减1
-
prim算法
- 类似于寻找图的最短路径,重复去找相连的点中代价最小的一条边,构造最小生成树。
- 时间复杂度是O(|V|^2)不依赖于|E|,适用于求解边稠密的图的最小生成树。
- 过程如图
-
Kruskal算法
- 按照权值的递增次序找合适的边,来构造最小生成树
- 时间复杂度O(|E|log|E|),所以适合于边稀疏顶点多的图
-
最短路径
- 广度优先遍历是找无权图的最短路径
- 带权图路径长度最短的就是最短路径
- 分类
- 单源最短路径 - Dijkstra
- 每个顶点间的最短路径 - Floyd
-
Dijkstra求单源最短路径
- 集合S记录最短路径的顶点,s[vi]=1表示顶点Vi放入了S。
- 辅助数组
- dist[]:记录V0到其他顶点当前的最短路径长度,dist[i]初始为arcs[v0] [i]
- path[]:path[i]表示源点到顶点i之间的最短路径的前驱结点,结束时可以追溯整条路径
- 基于贪心策略,时间复杂度O(|V|^2)
-
Floyd求个顶点直接的最短路径问题
- 基本思想:列出起始状态后,每次更新经过某个顶点,所有的路径是否变短
- 允许带负权值,单不允许包含负权值的边组成回路
-
拓扑排序
- 有向无环图:有向图中不存在环
- AOV网:若DAG图表示一个工程,顶点是活动,有向边<Vi,Vj>表示活动Vi必须在Vj前进行,这种顶点表示活动的网络就是AOV网。
- 拓扑排序满足
- 每个顶点只出现一次
- 顶点A在顶点B前面,则不存在顶点B到顶点A的路径
- 时间复杂度是O(|V|+|E|)
- 先找一个入度为0的结点,删除他的边,输出,重复。
-
关键路径
- 带权有向图中国,顶点表示事件,边表示活动(权值表示开销),叫作AOE网
- 性质
- 某顶点时间发生后,从这个顶点出发的各有向边代表的活动才开始
- 只有进入某一顶点的各有向边所代表的活动结束,该顶点所代表的的时间才能发生
- 开始顶点(入度为0)是源点,结束顶点(出度为0)是汇点。
- 最大路径长度的路径叫作关键路径,关键路径上的活动事关键活动
- 找关键活动的几个定义
- 事件Vk的最早发生时间Ve(k):开始顶点到Vk的最大路径长度
- 事件Vk的最迟发生时间V1(k):不推迟整个工程完成的前提下的最迟发生时间
- 活动最早开始时间
- 活动最迟开始时间
- 关键路径上的所有活动都是关键活动,可以通过加快关键活动来缩短工期,但可能会变成非关键
- 关键路径不是唯一的