2019-2020-26 《数据结构与面向对象程序设计》第10周学习总结
2019-2020-26 《数据结构与面向对象程序设计》第10周学习总结
教材学习内容总结
- 图
- 无向图
- 无向图中,表示边的顶点对是无序的
- 如果图中的两个顶点之间有边连接,则称它们是邻接的
- 如果无向图中连接顶点的边数达到最大,则图为完全图
- 第一个顶点和最后一个顶点相同且边不重复的路径称为环
- 有向图
- 在有向图中,边是顶点的有序对
- 有向图中的路径是连接图中两个顶点的有向边的序列
- 带权图
图的每条边上都有对应的权值称为带权图
- 邻接矩阵
- 用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵。
- 对无向图而言,邻接矩阵一定是对称的,而且主对角线一定为零(在此仅讨论无向简单图),副对角线不一定为0,有向图则不一定如此。
- 在无向图中,任一顶点i的度为第i列(或第i行)所有非零元素的个数,在有向图中顶点i的出度为第i行所有非零元素的个数,而入度为第i列所有非零元素的个数。
- 用邻接矩阵法表示图共需要n^2个空间,由于无向图的邻接矩阵一定具有对称关系,所以扣除对角线为零外,仅需要存储上三角形或下三角形的数据即可,因此仅需要n(n-1)/2个空间。
- 十字链表
- 十字链表(Orthogonal List)是有向图的另一种链式存储结构。可以看成是将有向图的邻接表和逆邻接表结合起来得到的一种链表。在十字链表中,对应于有向图中每一条弧都有一个结点,对应于每个定顶点也有一个结点。
- 也可以理解为 将行的单链表和列的单链表结合起来存储稀疏矩阵称为十字链表, 每个节点表示一个非零元素。
- 遍历
-
广度优先遍历
- 从图中的某一个顶点x出发,访问x,然后访问与x所相邻的所有未被访问的顶点x1、x2……xn,接着再依次访问与x1、x2……xn相邻的未被访问的所有顶点。依次类推,直至图中的每个顶点都被访问。
- 实现方法:
访问起始顶点,并将插入队列;
从队列中删除队头顶点,将与其相邻的所有的未被访问的顶点插入队列中;
重复第二步,直至队列为空。
未被访问的顶点怎么识别呢?利用顶点的isVisited属性来进行标记。
同时还需要另一个队列(或者是list)用来保存访问的顺序,另一个队列的顶点入队顺序就是图的广度遍历顺序,因此,该队列保持 与 前一个队列的顶点入队操作 一致。由于前一个队列是辅助遍历的,它有出队的操作,它就不能记录整个顶点的访问序列了,因此才需要一个保存访问顺序的队列。当整个过程遍历完成后,将 保存访问顺序的队列 进行出队操作,即可得到整个图的广度优先遍历的顺序了。
-
深度优先遍历
- 从图中的某一个顶点x出发,访问x,然后遍历任何一个与x相邻的未被访问的顶点y,再遍历任何一个与y相邻的未被访问的顶点z……依次类推,直到到达一个所有邻接点都被访问的顶点为止;然后,依次回退到尚有邻接点未被访问过的顶点,重复上述过程,直到图中的全部顶点都被访问过为止。
- 实现方法:
访问起始顶点,并将其压入栈中;
从栈中弹出最上面的顶点,将与其相邻的未被访问的顶点压入栈中;当深度优先遍历到某个顶点时,若该顶点的所有邻接点均已经被访问,则发生回溯,即返回去遍历 该顶点 的 前驱顶点 的 未被访问的某个邻接点。(相当于没有把新的节点压入栈中,下一个被访问的节点是当前节点下面的节点)
重复第二步,直至栈为空栈。
未被访问的顶点怎么识别呢?利用顶点的isVisited属性来进行标记。
对于深度优先而言,访问了 顶点A 时,紧接着只需要找到 顶点A 的一个未被访问的邻接点,再访问该邻接点即可。而对于广度优先,访问了 顶点A 时,就是要寻找 顶点A的所有未被访问的邻接点,再访问 所有的这些邻接点。
同时还需要另一个队列(或者是list)用来保存访问的顺序。
-
教材学习中的问题和解决过程
- 问题1:图的广度优先遍历和深度优先遍历最根本的区别是什么?
- 问题1解决方案:
一、指代不同
-
深度优先遍历:是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
-
广度优先遍历:系统地展开并检查图中的所有节点,以找寻结果。
二、特点不同
-
深度优先遍历:所有的搜索算法从其最终的算法实现上来看,都可以划分成两个部分──控制结构和产生系统。正如前面所说的,搜索算法简而言之就是穷举所有可能情况并找到合适的答案,所以最基本的问题就是罗列出所有可能的情况,这其实就是一种产生式系统。
-
广度优先遍历:并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
三、算法不同 -
深度优先遍历:把根节点压入栈中。每次从栈中弹出一个元素,搜索所有在它下一级的元素,把这些元素压入栈中。并把这个元素记为它下一级元素的前驱。找到所要找的元素时结束程序。如果遍历整个树还没有找到,结束程序。
-
5广度优先遍历:把根节点放到队列的末尾。每次从队列的头部取出一个元素,查看这个元素所有的下一级元素,把它们放到队列的末尾。并把这个元素记为它下一级元素的前驱。找到所要找的元素时结束程序。如果遍历整个树还没有找到,结束程序。
代码调试中的问题和解决过程
- 问题1:Dijkstra算法的代码表示
- 问题1解决方案:
public int[] dijkstra(int v) {
if (v < 0 || v >= numOfVexs)
throw new ArrayIndexOutOfBoundsException();
boolean[] st = new boolean[numOfVexs];// 默认初始为false
int[] distance = new int[numOfVexs];// 存放源点到其他点的矩离
for (int i = 0; i < numOfVexs; i++)
for (int j = i + 1; j < numOfVexs; j++) {
if (edges[i][j] == 0) {
edges[i][j] = Integer.MAX_VALUE;
edges[j][i] = Integer.MAX_VALUE;
}
}
for (int i = 0; i < numOfVexs; i++) {
distance[i] = edges[v][i];
}
st[v] = true;
// 处理从源点到其余顶点的最短路径
for (int i = 0; i < numOfVexs; ++i) {
int min = Integer.MAX_VALUE;
int index=-1;
// 比较从源点到其余顶点的路径长度
for (int j = 0; j < numOfVexs; ++j) {
// 从源点到j顶点的最短路径还没有找到
if (st[j]==false) {
// 从源点到j顶点的路径长度最小
if (distance[j] < min) {
index = j;
min = distance[j];
}
}
}
//找到源点到索引为index顶点的最短路径长度
if(index!=-1)
st[index] = true;
// 更新当前最短路径及距离
for (int w = 0; w < numOfVexs; w++)
if (st[w] == false) {
if (edges[index][w] != Integer.MAX_VALUE
&& (min + edges[index][w] < distance[w]))
distance[w] = min + edges[index][w];
}
}
return distance;
}
代码托管week10
上周考试错题总结
上周无考试,无错题
结对及互评
点评:
- 博客中值得学习的或问题:
- 对课本,代码进行多方位的思考。
- 认真寻找自己的不足之处。
- 举例说明问题。
- 代码中值得学习的或问题:
- 基于评分标准,我给本博客打分:14分。得分情况如下:
- 感想,体会不假大空的加1分
- 排版精美的加一分
- 结对学习情况真实可信的加1分
- 正确使用Markdown语法
- 模板中的要素齐全(加1分)
- 错题学习深入的加1分
- 点评认真,能指出博客和代码中的问题的加1分
- 教材学习中的问题和解决过程, 加5分
- 代码调试中的问题和解决过程,加2分
点评过的同学博客和代码
-
本周结对学习情况
- 赵沛凝20182301
- 结对照片
- 结对学习内容
- 图的广度优先遍历和深度优先遍历
-
上周博客互评情况
其他(感悟)
- 学习了图,回忆起了离散的内容。
- 开始写大实践,学习了后台布局的一些知识。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 26/200 | 2/2 | 7/7 | |
第二、三周 | 235/327 | 3/5 | 15/23 | |
第四周 | 123/450 | 2/7 | 8/31 | |
第五周 | 850/1300 | 2/9 | 9/40 | |
第六周 | 846/1696 | 2/11 | 7/47 | |
第七周 | 1614/3310 | 2/13 | 15/62 | |
第八周 | 360/3670 | 1/14 | 10/72 | |
第九周 | 2611/6281 | 2/16 | 10/82 | |
第十周 | 2348/8629 | 2/18 | 11/83 |
- 实际学习时间:11小时