1. 图的存储
1)邻接矩阵
2) 邻接表
一个数组存顶点,每个顶点对应一个单链表
3) 十字链表
firstin指向入度结点,tailvex表示边的起点,headvex边的终点。可以方便的求每个结点的入度
2.图的遍历
深度和广度优先时间复杂度一样
广度更加适合找距离最近的最优点
3. 最小生成树
生成树:包含图中所有顶点,边数为使得所有顶点连通的最小值。假设共有n个顶点,那么边数为n-1。
最小生成树:边权值和最小的生成树
生成最小生成树的算法:
1)prim算法,适合边很多的图,O(n2)
两个顶点集vs1,vs2,在vs1中任意放一个顶点,其余顶点放到vs2, 在vs2中取出一个与vs1中顶点邻接,但是边权值最小的点,加入vs1,重复加点,直至vs2空。
证明:https://blog.csdn.net/daimaliang/article/details/89075551
2)kruskal算法,适合边较少,O(eloge)
所有顶点设置一个标记,标记相同表示在同一个生成树中,先将所有边按权值升序排列,然后遍历这些边,取一条边后查看其左右顶点的标记是否相同,如果相同那么说明已经在同一个生成树中,这条边如果加进去就会形成回路,故跳过,如果标记不同,说明两个顶点位于不同的生成树,可以连接,连接后将其中一个生成树包含的所有顶点的标记值全部改为和另一个生成树一样,知道边集中有了n-1条边。
http://data.biancheng.net/view/41.html
4. 最短路径
1)dijkstra算法
一次性求任意点v到其余所有点的最短路径。先考虑v的邻接点,再从邻接点向外扩展。
定义一个dist数组,表示每个点到v的当前最短距离,定义一个集合S,放置所有已确定到v最短距离的点,初始放入点v。
第一步,初始化dist数组,v的邻接点的直接得出数值,非邻接点当前取无穷大。然后把dist数组中最小的值对应的点vi放入S,因为不可能通过其他点的传递使得dist[vi]更小。当我们把vi放入S,就要考虑其余的点vj借助vi能否使得dist[vj]值变小,即判断edgeij+dist[vi]是否大于dist[vj]。
第二步,如果vi的邻接点借助vi可以使得到达v的距离更短就更新其dist值,并记录其前驱结点为vi. 更新完dist之后再不dist中最小的值对应的点vt放入S, 因为dist[vt]当前最小,借助其他结点到达vt,只会使得dist[vt]变大。
第三步,继续上述操作,直至所有点放入S.
https://blog.csdn.net/qq_35644234/article/details/60870719
2)floyd算法
dijkstra完成一个点到其他所有点的最短距离,floyd是计算出所有点到任意点的最短路径。
算法过程是不断更新D数组,最初的D数组里的值是点到点不经过任何中间结点的distance。
第一步利用v0作为中间结点来重新计算D数组所有值。判断D[vi][vj]与D[vi][v0]+D[v0][vj]谁更小。如果借助v0可以得到更小的距离,那么更新。
第二步,接下来再用v1到v8的分别重复第一步,最后得到的数组就是最终结果。
5. 拓扑排序
图中每个结点都代表一个活动,这些活动之间有先后顺序,前面的活动不完成,那么后面的活动就无法开始,我们根据活动之间的关系来给出一个活动序列,满足活动的先后顺序,求这个序列的过程叫拓扑排序。这个AOV网不能有回路。
上图的先后关系容易看出,也意味着拓扑排序容易完成。但对于下面这个AOV网就不容易写出拓扑序列。我们需要按照一定的规则来完成。
首先起点必然是入度为0的结点,因为他没有前驱结点,不需要等待其他结点代表的活动完成。例如先print V0,然后删除V0以及V0连接的三条边,这时v4,v11,v5的入度都同时减一,然后我们再次寻找下一个入度为0的结点例如v1,这样持续下去直至没有入度为0的点,此时如果还有没有打印的点,说明图中有回路。
6. 关键路径
1. 在一个无回路的有向网络中,如果只有一个源点(入度为0)和一个汇点(出度为0),那么从源点到汇点最长的路径称之为“关键路径”。每个工程项目都有一个开始事件和一个结束事件,可以看作为源点和汇点。每条边的权重代表一个活动持续的时间。
2. 关键路径上的活动(边)称之为关键活动,为了求出一个工程最短耗时多久我们需要找出所有关键活动,而为了明确什么是关键活动我们需要定义 :
1)活动<i,j>最早发生时间:事件vi最早发生时间
2)活动<i,j>最迟发生时间: 事件vj最迟发生时间 减去活动<i,j>的长度。
关键活动:最早发生时间等于最迟发生时间的活动,即刻不容缓,能早就早,因为关键活动决定了整个工程的工期,关键活动拖延就会使得工程进度拖延。
可以发现活动的最早发生时间和最迟发生时间都是和事件的发生时间相关的。
事件最早发生时间:事件5的最早发生时间取决于事件v2和v3的最早发生时间,earliest(v5)=max( earliest(v2)+a4, earliest(v3)+a5) ,因为必须v2和v3都发生了事件5才发生。
事件最迟发生时间:事件5的最迟发生时间取决于v7和v8的最迟发生时间,latest(v5)=min( latest(v7)-a7, latest(v8)-a11 ),因为不能使得v7和v8的最迟发生时间推迟,所以v7,v8谁要求更早,就按谁的要求来。
从上述求法可以看出求事件的最早发生时间是从前到后的过程(从源点开始),而求事件的最迟发生时间是从后到前的过程(从汇点开始,汇点的最迟发生时间等于其最早发生时间)