DS博客作业04--图

0.PTA得分截图

图题目集总得分,请截图,截图中必须有自己名字。题目至少完成2/3,否则本次作业最高分5分。

1.本周学习总结(6分)

比起前一章的树,图的结构体、基础函数等都会简单一些,结构体很简单,基本函数也没有像树那样经常用到递归,但是那些Prim等算法还是需要花点时间去理解的。
2.图的存储结构分为邻接矩阵和邻接表,邻接矩阵适用于稠密图,邻接表适用于疏密图。用邻接矩阵进行BFS、DFS,用邻接表进行BFS、DFS遍历的操作都需要我们非常熟悉。
3.当在一个不带权图中搜索从一个顶点到另一个顶点的一条路径时,DFS求出的路径不一定时最短路径,而BFS求出的路径一定是最短路径。
4.Prim算法和克鲁斯卡尔算法都是求最小生成树的算法,采用邻接矩阵最合适。从理论上来讲(不看代码),克鲁斯卡尔算法更容易理解,只要将线段从小到大排序后再连接就好了,
但是Prim算法在代码上更容易实现。
5.Dijkstra算法和Floyd算法,前者输出单源路径,后者输出多源路径。.Dijkstra算法其实和Prim算法有很多相似,但需要修正的数据会比Prim算法多。
本次所有总结内容,请务必自己造一个图(不在教材或PPT出现的图),围绕这个图展开分析。建议:Python画图展示。
图的结构尽量复杂,以便后续可以做最短路径、最小生成树的分析。

1.1 图的存储结构

1.1.1 邻接矩阵(不用PPT上的图)

造一个图,展示其对应邻接矩阵

邻接矩阵的结构体定义

建图函数

1.1.2 邻接表

造一个图,展示其对应邻接表(不用PPT上的图)

邻接矩阵的结构体定义

建图函数

1.1.3 邻接矩阵和邻接表表示图的区别

对于一个n个顶点e条边的无向图,它的邻接表表示有n个顶点表结点2e个边表结点
对于一个n个顶点e条边的有向图,它的邻接表表示有n个顶点表结点e个边表结点

在邻接表中第i个边表的结点个数就是顶点Vi的度,在有向图中求顶点的度采用邻接矩阵比采用邻接表表示更方便

各个结构适用什么图?时间复杂度的区别
在有向图中,求出度和入度:
邻接表表示中第i个边表上的结点个数就是顶点Vi的出度,求入度较困难,需遍历个顶点的边表
逆邻接表表示中第i个边表上的结点个数就是顶点Vi的入度,求出度较困难,需遍历个顶点的边表

如果图中边的数目远远小于n2称作稀疏图,这是用邻接表表示比用邻接矩阵表示节省空间;
如果图中边的数目接近于n2,对于无向图接近于n*(n-1)称作稠密图,考虑到邻接表中要附加链域,采用邻接矩阵
表示法为宜
在邻接矩阵中求边的数目必须检测整个矩阵,所消耗的时间是O(n)
在邻接表中求边的个数,只要对每个边表计数即可求得所消耗的时间是O(n+e)

1.2 图遍历

图的遍历的概念
从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访间图中的所有顶点,使每个顶点仅被访问一次,
这个过程称为图的遍历。图的遍历得到的顶点序列称为图遍历序列。根据搜索方法的不同,图的遍历方式分为两种。

1.2.1 深度优先遍历

深度优先搜索遍历的过程是:从图中某个初始顶点 v 出发,首先访问初始顶点 v ,然后迭择一个与顶点 v 相邻且没被访问过的
顶点 w 为初始顶点,再从 w 出发进行深度优先搜索,直到图中与当前顶点 v 邻接的所有顶点都被访问过为止。显然,这个遍历
过程是个递归过程。
选上述的图,继续介绍深度优先遍历结果

深度遍历代码

深度遍历适用哪些问题的求解。(可百度搜索)
转自知乎

1.2.2 广度优先遍历

广度优先遍历的过程是:初始点v首先访问初始点vi 接着访问vi的所有来被访问过的邻接点vi1,vi2,vit,然后再
按照vi1,vi2,vit的次序,访问每一个顶点的所有未被访问过的邻接点,依次类推,直到图中所有和初始点vi有路径
相通的顶点都被访问过为止。

广度遍历代码

广度遍历适用哪些问题的求解。(可百度搜索)
百度

1.3 最小生成树

用自己语言描述什么是最小生成树。
生成树是一个连通图的最小联通子图,它含有图中的全部顶点,但只有足够构成一棵树的n-1条边,当这些边带上权值,
权值最小的树为最小生成树。

1.3.1 Prim算法求最小生成树

基于上述图结构求Prim算法生成的最小生成树的边序列
实现Prim算法的2个辅助数组是什么?其作用是什么?Prim算法代码。
分析Prim算法时间复杂度,适用什么图结构,为什么?

1.3.2 Kruskal算法求解最小生成树

置U的初值等于V(即包含有G中的全部顶点),TE的初值为空集(即图T中每一个顶点都构成一个连通分量)。
将图G中的边按权值从小到大的顺序依次选取: 若选取的边未使生成树T形成回路,则加入TE;否则舍弃,直到TE中包含(n-1)条边为止。
图解:
基于上述图结构求Kruskal算法生成的最小生成树的边序列
实现Kruskal算法的辅助数据结构是什么?其作用是什么?Kruskal算法代码。
void Kruskal(AdjGraph *g) { int i,j,u1,v1,sn1,sn2,k; int vset[MAXV]; //集合辅助数组 Edge E[MaxSize]; //存放所有边 k=0; //E数组的下标从0开始计 for (i=0;i<g.n;i++) //由g产生的边集E,邻接表 { p=g->adjlist[i].firstarc; while(p!=NULL) { E[k].u=i;E[k].v=p->adjvex; E[k].w=p->weight; k++; p=p->nextarc; } } Sort(E,g.e); //用快排对E数组按权值递增排序 for (i=0;i<g.n;i++) //初始化集合 vset[i]=i; k=1; //k表示当前构造生成树的第几条边,初值为1 j=0; //E中边的下标,初值为0 while (k<g.n) //生成的顶点数小于n时循环 { u1=E[j].u;v1=E[j].v; //取一条边的头尾顶点 sn1=Find(u1,vset); sn2=Find(v1,vset); //分别得到两个顶点所属的集合编号 if (sn1!=sn2) //两顶点属于不同的集合 { printf(" (%d,%d):%d\n",u1,v1,E[j].w); k++; //生成边数增1 vset[sn1]=sn2; } j++; //扫描下一条边 } } int Find(int v,int vest[]) { if(vset[v]==v) return v; else return Find(vset[v],vset) }
分析Kruskal算法时间复杂度,适用什么图结构,为什么?

1.4 最短路径

考虑带权有向图,把一条路径(仅考虑简单路径)上所经过的权值之和定义为该路径的路径长度或称带权路径长度,
路径长度最短的那条路径称为最短路径。

1.4.1 Dijkstra算法求解最短路径(解决“单节点-所有结点”间的最短路径问题)

基本思想:
以某一结点(源结点)为出发点,在与其相连且尚未被加入的结点里,选择加入离出发点距离最短的结点,并且通过
新加入的结点更新出发点到其他结点的距离,如此重复加入新结点,直到所有的结点都被加入为止。

基于上述图结构,求解某个顶点到其他顶点最短路径。(结合dist数组、path数组求解)

Dijkstra算法需要哪些辅助数据结构

Dijkstra算法如何解决贪心算法无法求最优解问题?展示算法中解决的代码。
Dijkstra算法的时间复杂度,使用什么图结构,为什么。

1.4.2 Floyd算法求解最短路径

Floyd算法解决什么问题?
Floyd算法需要哪些辅助数据结构
Floyd算法优势,举例说明。

1.5 拓扑排序

拓扑排序,是定义在有向图上的一种操作,目的是根据结点间关系求得结点的一个线性排列(这与遍历操作的
目的相似)。
找一个有向图,并求其对要的拓扑排序序列

实现拓扑排序代码,结构体如何设计?


书写拓扑排序伪代码,介绍拓扑排序如何删除入度为0的结点?

如何用拓扑排序代码检查一个有向图是否有环路?
若图中没有一个没有前驱的结点V,则存在环路。

1.6 关键路径

什么叫AOE-网?
AOE(Activity On Edge)网络
用一个带权有向图(DAG)描述工程的预计进度。顶点表示事件,有向图表示活动,边e的权c(e)表示完成活动e
所需要的时间(比如天数)。图中入度为0的顶点表示工程的开始时间(如开工仪式),出度为0的顶点表示工程
事件
什么是关键路径概念?
关键路径表示,从有向图的原点到汇点的最长路径。
什么是关键活动?
关键活动表示,该弧上的权值增加将使得有向图上的最长路径的长度增加。

2.PTA实验作业(4分)

2.1 六度空间(2分)

选一题,介绍伪代码,不要贴代码。请结合图形展开分析思路。

2.1.1 伪代码(贴代码,本题0分)

伪代码为思路总结,不是简单翻译代码。

2.2 村村通或通信网络设计或旅游规划(2分)

2.2.1 伪代码(贴代码,本题0分)

伪代码为思路总结,不是简单翻译代码。

posted @ 2021-05-23 22:31  calizo  阅读(201)  评论(0编辑  收藏  举报