20162305 2017-2018-1 《程序设计与数据结构》第11周学习总结
教材学习内容总结
- 哈希算法:哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母,随后的哈希都将产生不同的值。要找到散列为同一个值的两个不同的输入,在计算上是不可能的,所以数据的哈希值可以检验数据的完整性。一般用于快速查找和加密算法。
- 哈希函数:哈希函数(英语:Hash Function)是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,重新创建一个叫做散列值的指纹。散列值通常用来代表一个短的随机字母和数字组成的字符串。好的散列函数在输入域中很少出现散列冲突。在散列表和数据处理中,不抑制冲突来区别数据,会使得数据库记录更难找到。
- 除法方法:通过除法方法建立哈希函数,指用关键字除以某个正整数P后的余数,作为给定元素的下标。
- 折叠方法:将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址
- 平方取中法:取关键字平方后的中间几位为哈希地址。
- 基数转换方法:关键字转换为另一种数值基数,使用除法方法将转换后的值除以表长,并用余数作为下标。
- 数字分析方法:抽取关键字中的指定位置并进行处理从而得到下标。
- 长度依赖方法:关键字和关键字的长度以某些方式组合起来,或直接当做下标使用,或再进一步使用其他方法进行处理而得到下标。
课程学习内容总结
一、图的存储结构及其实现
1、邻接矩阵
- 用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵。用邻接矩阵表示图,很容易确定图中任意两个顶点是否有边相连。邻接矩阵分为有向图邻接矩阵和无向图邻接矩阵。对无向图(无向简单图)而言,邻接矩阵一定是对称的,而且对角线一定为零,有向图则不一定如此。
- 无向图的邻接矩阵对称,可压缩存储;
无向图中顶点vi的度是邻接矩阵中第i行1的个数。
- 有向图邻接矩阵不一定对称;
有向图中,顶点vi的出度是邻接矩阵中第i行1的个数。顶点vi的入度是邻接矩阵中第i列1的个数。
- 采用邻接矩阵表示图,直观方便,运算简单。
1)时间复杂度
边查找:对于查找图中任两个顶点i和j之间有无边,以及边上的权值,可根据i, j的值随机查找,时间复杂性为O(1)。
顶点度计算:计算一个顶点的度(或入度、出度)和邻接点,其时间复杂性为O(n)。
2)空间复杂度:O(n2)
如果用来表示稀疏图,则会造成较大的空间浪费。
2、边集数组
- 边集数组(edgeset array)是利用一维数组存储图中所有边的一种图的表示方法。该数组中所含元素的个数要大于等于图中边的条数,每个元素用来存储一条边的起点、终点(对于无向图,可选定边的任一端点为起点或终点)和权(若有的话),各边在数组中的次序可任意安排,也可根据具体要求而定。
- 边集数组中所含元素的个数要大于等于图中边的条数。
1)时间复杂度
顶点度计算:若一个图中有e条边,n个顶点,在边集数组中查找一条边或一个顶点的度都需要扫描整个数组,所以其时间复杂度为O(e)。
顶点或边的查找:在边集数组中查找一条边或一个顶点的度都需要扫描整个数组,所以其时间复杂性为O(e)。
2)空间复杂度
边集数组表示一个图需要一个边数组和一个顶点数组,所以其空间复杂度为O(n+e)。从空间复杂度上讲,边集数组也适合表示稀疏图。
3、邻接表
- 邻接表是图的一种链式存储结构。对图的每个顶点建立一个单链表(n个顶点建立n个单链表),第i个单链表中的结点包含顶点Vi的所有邻接顶点。又称链接表。
- 无向图
- 若无向图中有 n 个顶点、e 条边,则其邻接表需 n 个
头结点和2e 个表结点。适宜存储稀疏图
无向图中顶点 vi 的度为第 i 个单链表中的结点数。
- 有向图
- 顶点 vi 的出度为第 i 个单链表中的结点个数。
顶点 vi 的入度为整个单链表中邻接点域值是i -1 的结点个数。
找出度易,找入度难。
4、十字链表
- 十字链表是有向图的另一种存储结构,目的是将在有向图的邻接表和逆邻接表中两次出现的同一条弧用一个结点表示,由于在邻接表和逆邻接表中的顶点数据是相同的,则在十字链表中只需要出现一次,但需保留分别指向第一条"出弧"和第一条"入弧"的指针。
- 十字链表除了结构复杂一点外,其创建图的时间复杂度是和邻接表相同的,用十字链表来存储稀疏有向图,可以达到高效存取的效果,因此,在有向图的应用中,十字链表也是非常好的数据结构模型。
二、图的遍历
1、图的广度优先遍历
- 从一个顶点开始,辐射状地优先遍历其周围较广的区域,故称之为广度优先遍历。
需要一个队列来保存遍历过的顶点顺序,以便按出队的顺序再去访问这些顶点的邻接顶点。
2、图的深度优先遍历
- 设x是当前被访问顶点,在对x做过访问标记后,选择一条从x出发的未检测过的边(x,y)。若发现顶点y已访问过,则重新选择另一条从x出发的未检测过的边,否则沿边(x,y)到达未曾访问过的y,对y访问并将其标记为已访问过;然后从y开始搜索,直到搜索完从y出发的所有路径,即访问完所有从y出发可达的顶点之后,才回溯到顶点x,并且再选择一条从x出发的未检测过的边。上述过程直至从x出发的所有边都已检测过为止。
三、图中的树问题
1、生成树
- 连通图G的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G的生成树。
2、最小生成树
- 最小生成树其实是最小权重生成树的简称。一个有n个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有n个结点,并且有保持图连通的最少的边。最小生成树可以用kruskal(克鲁斯卡尔)算法或Prim(普里姆)算法求出。
3、最小生成树-Prim算法
- 从连通网络 N = { V, E }中的某一顶点 u0 出发, 选择与它关联的具有最小权值的边(u0, v),将其顶点加入到生成树顶点集合U中。
以后每一步从一个顶点在 U 中, 而另一个顶点不在 U 中的各条边中选择权值最小的边(u, v),把它的顶点加入到集合 U 中。如此继续下去, 直到网络中的所有顶点都加入到生成树顶点集合 U 中为止。
4、最小生成树-Kruskal算法
- 从边出发,直接找最小权值的边来构建生成树。
四、图中的最短路径问题
1、单源最短路径——Dijkstra算法
五、活动顶点与活动边的问题
1、AOV网与拓扑排序
- 顶点表示活动、边表示活动间先后关系的有向图称做顶点活动(Activity On Vertex)网,简称AOV网。
- 使AOV网中的各个顶点排成一个线性序列,该序列保持各个顶点原有的优先关系,而对于原先没有先后关系的顶点则建立起人为的先后关系,这个排序过程称为拓扑排序。
- 拓扑排序
2、AOE网与关键路径
- AOE网是表示工程流程的带权有向图,其中顶点表示事件,有向边表示活动,边上的权值表示活动的持续时间。
- (1)只有在某顶点所代表的事件发生后,从该顶点出发的各有向边所代表的活动才能开始。
(2)只有在进入某点的各有向边所代表的活动都已结束,该顶点所代表的时事件才能发生。
AOE网只有一个源点一个汇点
- 关键路径的特点
- 关键路径上所有活动的持续时间总和就是项目的工期。
- 关键路径上的任何一个活动都是关键活动,其中任何一个活动的延迟都会导致整个项目完工时间的延迟。
- 若缩短关键路径的总耗时,会缩短项目工期;反之,则会延长整个项目的总工期。
- 改变关键活动的耗时,可能使关键路径发生变化。
- 可以存在多条关键路径
代码托管
(statistics.sh脚本的运行结果截图)
上周考试错题总结
- 解析出来后更新
本周结对学习情况
- 20162306
- 结对学习内容
- 图
其他(感悟、思考等,可选)
本周继续对图的学习,学习了有关图的性质,这部分的内容学起来感觉有些困难,对代码实现也不是很清楚,还需要继续学习。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 18/38 | |
第三周 | 500/1000 | 3/7 | 22/60 | |
第四周 | 300/1300 | 2/9 | 30/90 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
- 计划学习时间:XX小时
- 实际学习时间:XX小时
- 改进情况:
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)