数据结构图,C语言洛谷写题,前端OPPO首页案例
一.数据结构 图
(一)图的基本概念
- 图G是由两个集合V和E组成的,V是顶点的集合,E是两个不同顶点边的集合
- 无向完全图有
条边,有向完全图有
条边<只考虑出边的话,与之相关的出边有
个,总共
个顶点>
- 简单路径:一条路径上除开始点和结束点外,其他点都不一样
- 路径长度:经过边的数量
- 回路或环:开始点和结束点是一个
- 连通图,连通分量,强连通图,强连通分量:分别对于无向图、有向图来说,任意两个顶点都是连通的;极大连通子图为连通分量
- 权:边上的数值; 边上带权的图称为带权图或网
- 所有顶点的度之和等于边数的两倍(度之和=2*e)<因为每条边作为两个邻接点的度各计了一次>
(二)图的存储结构,基本算法
- 领接矩阵(唯一,稠密图)
#define MAXV #define INF 32767 typedef struct { int no; //顶点编号 InfoType info; //顶点的其他信息 }VertexType; //顶点的类型 typedef struct { int edges[MAXV][MAXV]; //邻接矩阵数组 int n,e; //顶点数,边数 VertexType vexs[MAXV]; //存放顶点信息 }MatGragh; //完整的图邻接矩阵类型
-
邻接表(不唯一,稀疏图)<顺序与链式相结合的存储方式>
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; //图的邻接表类型
-
十字链表
-
邻接多重表
-
(三)图的遍历
1.图的遍历:从图中的指定顶点出发,按某种方法访问图中的所有顶点,使得每个顶点仅被访问一次
2.深度优先遍历(DFS):
- 从v出发,选择一个未被访问过的邻接点w访问,再选择w的未被访问过的邻接点继续访问...
- 先进后出的特点,栈或递归实现
- 距离初始顶点越远越优先被访问
3.广度优先遍历(BFS):
- 从v出发,找v所有未被访问的邻接点v1、v2...
- 先进先出的特点,队列实现
- 距离初始顶点越近越优先访问
4.非连通图的遍历:每个连通分量调用一次算法
5.DFS和BFS的应用
(四)生成树、最小生成树
1.生成树:连通图的生成树是一个极小的连通子图,含有图中所有的n个顶点,和构成一棵树的(n-1)条边。
2.一颗生成树上加任何一条边,构成一个环
3.有且仅有(n-1)条边,否则是非连通图
4.最小生成树:图中所有生成树中具有边上的权值之和最小的树
5.深度优先生成树(DFS tree)、广度优先生成树(BFS tree)
6.普里姆(Prim)算法(稠密图)
- 构造性算法
- 增量算法
- 局部最优-->全局最优
- U :已经确定的顶点集合 V-U:候选边的顶点集合
- 一步一步的选择最小边(权最小的边)
- closest[]数组保存U中的这个顶点,lowcost[]数组保存边的权
- 在V-U中找最小的权放在min中,并将该顶点加到U中,将其权值改为0,表示已经加到了U中
- 如果本次加入的权比之前保存的小就要更新
7.克鲁斯卡尔(Kruskal)算法(稀疏图)
-
按权值的递增次序来选择适合的边构造最小生成树
-
所有边按权值递增排序
-
依次选择边,不构成回来加入,构成回路不加入
-
连通分量编号vset[]来判断是否构成回路,增加一条边就将相关顶点改为相同的连通分量
(五)最短路径
1.最短路径一定是简单路径
2.狄克斯特拉(Dijkstra)算法
- 源点v到G中其他顶点的最短路径
- 单源路径最短问题
- 两个集合 S:初始时只包括源点 U=V-S
- 找最小的长度路径的顶点u
- 从U中选择一个顶点u加入S
- 比较 不经过u到j的路径长度 和 经过u到j的路径长度
- 一维数组 dist :存放最短路径长度 path:存储n-1条最短路径(存放他的上一个顶点是谁)
3.费洛伊德(Floyd)算法
- 每对顶点之间的最短路径和最短路径长度
- 多源路径最短问题
- 迭代(递推)思想
表示
->
的路径上所经过的顶点编号不大于k的最短路径长度
- 每考虑一个顶点判断一次需不需要更新
- 二维数组 A :存储最短路径长度 path:最短路径
4.对于多源最短路径问题,也可以从每个顶点调用Dijkstra算法来计算,但相对而言,Floyd算法的性能更好
(六)拓扑排序
1.拓扑序列:<i,j>有路径,且顶点i必须排在顶点j前
2.拓扑排序:找拓扑序列的过程
3.步骤:
- 找没有前驱结点的顶点,输出它
- 删除该顶点出发的所有边
- 重复,直到不存在无前驱的顶点
4.全部被输出:不存在回路
(七)AOE与关键路径
- AOE网:边表示活动的网,顶点表示事件,边表示活动,边上的权表示活动所需的时间,入度为0(源点)的表示工程的开始事件,出度为0(汇点)的表示工程的结束事件
- 关键路径:从源点到汇点的所有路径中具有最大路径长度的路径
- 关键活动:在关键路径上的活动
- 最早开始时间 : 源点v的为0 从左往右 最大值
- 最迟开始时间: 不影响工程,事件v必须开始的时间 从右往左
- 关键活动:不存在富裕时间,即 最早开始时间=最迟开始时间