图的相关概念
- 顶点:顶点集非空;
- 边:边集可空;有向边 <i , j>、无向边 (i , j)
- 图:简单图、无向完全图、有向完全图、子图、稀疏图、网
- 连通图和强连通图:连通子图和强连通子图、连通分量和强连通分量
- 生成树和生成森林
- 简单路径和简单回路
图的存储结构
- 邻接矩阵:存储稀疏图时往往会造成大量空间浪费
#define MAXV 100
#define INF 32767
typedef struct
{ int no; //顶点编号
InfoType info; //顶点其他信息
}VertexType;
typedef struct
{ int edges[MAXV][MAXV]; //邻接矩阵数组
int n, e; //顶点数、边数
VertexType vexs[MAXV]; //存放顶点信息
}MatGraph;
- 邻接表:当存储有向图时,找出度容易,找入度难;逆邻接表找入度容易,找出度难
typedef struct ANode
{ int adjvex; //该边的邻接点编号
struct ANode *nextarc; //指向下一条边的指针
int weight; //边的权值
}ArcNode;
typedef struct Vnode
{ InfoType info; //顶点的其他信息
ArcNode *firstarc; //指向第一个边结点
}VNode;
typedef struct
{ VNode adjlist[MAXV]; //邻接表的头结点数组
int n, e; //图的顶点数、边数
}AdjGraph;
- 十字链表:当存储有向图时,邻接表和逆邻接表的结合,出度和入度皆可存储
- 邻接多重表:当关注对无向图的边操作时,此存储结构优异
- 边集数组:只适合对边的操作,不适合对顶点的操作
图的遍历
- 深度优先遍历(DFS):类似树的前序遍历;使用递归执行操作,visited数组必须置为全局变量,时间复杂度大
- 广度优先遍历(BFS):类似树的层序遍历;使用队列执行操作,visited数组不必全局,空间复杂度大
构造最小生成树(关于有环无向图)
- Prim算法:以顶点为目标来构造
- Kruskal算法:以边为目标来构造
应用场景:在多个城市间建造高速公路使得造价最小、其他规划问题
求解最短路径问题(关于有环无向图)
- Dijkstra算法:针对单源最短路径的求解,即从某个顶点到其他每个顶点的最短路径
- Floyed算法:针对所有顶点间的最短路径求解
应用场景:求解迷宫问题、博弈问题
拓扑排序(关于无环有向图)
- 主要针对于AOV网(顶点表示活动);拓扑序列用于判断某个AOV网中是否存在环
- 拓扑排序算法:依次找入度为0的点,输出并删除与其相连的所有边;最终输出拓扑序列
应用场景:判断AOV网中是否存在环(无环的AOV网非常有实用价值,确保了某工程可以顺序进行)
求解关键路径问题(关于无环有向图)
- 主要针对于AOE网(边表示活动,顶点表示事件)
- ve(j) :顶点 j 的最早开始时间,即事件;从前往后算,无入度的顶点ve=0,其他顶点 ve(x) = Max(ve(x-1) + w)
- vl(k) :顶点 k 的最晚开始时间;从后往前算,无出度的顶点vl=ve,其他顶点 vl(x) = Min(vl(x+1) - w)
- e(i):边 i 的最早开始时间,即活动;e(i) = ve(j)
- l(i):边 i 的最晚开始时间;l(i) = vl(k) - w
- l(i) - e(i):活动的时间余量,余量为0则说明该活动为关键活动
应用场景:计算某工程所需的最短时间