2018-2019-20172321 《Java软件结构与数据结构》第九周学习总结

教材学习内容总结

第15章 图

无向图

  • 图由顶点组成。

    • 顶点由名字或标号来表示,如:A、B、C、D;
    • 边由连接的顶点对来表示,如:(A,B),(C,D),表示两顶点之间有一条边。
  • 无向图:与树类似,图也由结点和这些结点之间的连接构成。这些结点是顶点,而结点之间的链接是边。无向图是一种边为无序结点对的图。于是,记做(A,B)的边就意味着A与B之间有一条从两个方向都可以游历的连接。边记作(A,B)和记作(B,A)的含义是完全一样的。

  • 邻接(邻居):两个顶点之间有边连接。
  • 自循环(悬挂):自己连接到自己的边。
  • 完全图:含有最多 条边的无向图。例如:

无向图G是一个完全图。

  • 路径:连接图中两个顶点的边的序列,可以由多条边组成。

无向图中的路径是双向的。

  • 路径长度:路径中所含边的数目(顶点个数减1 )。
  • 连通图:无向图中 任意两个顶点间都有路径。例如:

完全图一定是连通图,连通图不一定是完全图。

  • 环(回路):第一个顶点与最后一个顶点相同且没有重复边的路径。例如:

  • 无环图:没有环的图。
  • 子图:类似集合中“子集”的概念,示例如下:

其中,(b),(c)是(a)的子图。

  • 生成树:包含无向图G1所有顶点的极小连通子图称为G1的生成树。例如:

  • 稀疏图与稠密图:有很少条边或弧(如 e < n lognn,n 是图的顶点数,e 是弧数)的图称为稀疏图,反之称为稠密图。

有向图

  • 有向图:顶点之间有序连接,边是顶点的有序对。

边(A,B)和(B,A)方向不同。

  • 有向路径:连接两个顶点有向边的序列。
  • 有向图中的有序对常用序偶表示,例如:

上图中路径 V00→V22→V33 是从V00到V33的路径,但是反过来不再成立。

  • 注意连通有向图与无向图不同,有向边决定连通性。例如:

上图中左图为联通图,右图不联通,因为从任何顶点到顶点1都没有路径。

  • 有向树是一个有向图,其中指定一个元素为根,则具有下列特性:

任何顶点到根都没有连接。

到达每个非根元素的连接都只有一个。

从根到每个顶点都有路径。

  • 顶点的度、出度、入度:

网络

  • 网络:(加权图)是一种每条边都带有权重或代价的图。

网络可以是无向的也可以是有向的。

常用图的算法

  • 遍历

  • 广度优先遍历:类似于树的层序遍历, 从一个顶点开始,辐射状地优先遍历其周围较广的区域。

    • 广度优先遍历算法:若顶点A先于顶点B被访问,则顶点A的邻接点也先于顶点B的邻接点被访问。特点:先把起始顶点附近的顶点访问完,再访问远处的顶点。在广度优先遍历算法的具体实现中,需要两个队列。一个辅助遍历,保存遍历过程中遇到的顶点,当访问完成了某个顶点A后,将A出队列,紧接着将A的所有邻接点都入队列,并访问。
  • 深度优先遍历:图的深度优先搜索,类似于树的先序遍历, 所遵循的搜索策略是尽可能“深”地搜索图。
    • 在深度优先遍历中,需要两个栈,这里可以看出深度优先遍历带有递归的性质。一个栈用来辅助遍历,即用来保存遍历过程中里面的顶点,另一个栈用来保存遍历的顺序。之所以另外需要一个栈来保存遍历的顺序的原因 与 广度优先遍历 中需要用另一个队列来保存 遍历顺序 的原因相同。当深度优先遍历到某个顶点时,若该顶点的所有邻接点均已经被访问,则发生回溯,即返回去遍历 该顶点 的 前驱顶点 的 未被访问的某个邻接点。

图的深度优先遍历与广度优先遍历的唯一不同是,他使用的是栈而不是队列来管理遍历。

  • 连通性:从任意结点开始的广度优先遍历中得到的顶点数等于图中所含顶点数。
  • 生成树:包含图中所有顶点及图中部分边的一棵树。
  • 最小生成树:所含边权值之和小于其他生成树的边的权值之和。
    • 因为树总是图,对于有些图来说,图本身就是一颗生成树,所以这样的图的生成树中将包含全部的边。
    • 最小生成树是其所含边的权值之和小于等于图的任意其他生成树的边的权值之和的生成树。

通常构造最小生成树的算法有两种:

① Prim算法: ① Prim算法: ① Prim算法:

它是从点的方面考虑构建一颗MST,大致思想是:设图G顶点集合为U,首先任意选择图G中的一点作为起始点a,将该点加入集合V,再从集合U-V中找到另一点b使得点b到V中任意一点的权值最小,此时将b点也加入集合V;以此类推,现在的集合V={a,b},再从集合U-V中找到另一点c使得点c到V中任意一点的权值最小,此时将c点加入集合V,直至所有顶点全部被加入V,此时就构建出了一颗MST。因为有N个顶点,所以该MST就有N-1条边,每一次向集合V中加入一个点,就意味着找到一条MST的边。

② Kruskal算法: ② Kruskal算法: ② Kruskal算法:

假设 WN=(V,{E}) 是一个含有 n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含 n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有 n 棵树的一个森林。之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林中只有一棵树,也即子图中含有 n-1条边为止。

  • 判定最短路径:

    • 判定起始顶点和目标顶点之间是否存在最短路径(两个顶点之间边数最少的路径)。
    • 在带权图中找到最短路径。(Dijkstra算法)
    • 最短路径算法:在边不带权值的图中求顶点A到顶点B的最短路径--其实就是顶点A到顶点B之间的最少边的条数。调用最短路径算法之前,首先要确定一个初始顶点,图中其他顶点的路径长度都是相对于初始顶点而言的。求两个顶点间最短路径,其实并不是找出两个顶点间所有的路径长度,然后取最小值。而是借助于广度优先遍历算法,将每个顶点相对于初始顶点的最短路径长度保存在 cost 属性中,广度优先算法的性质保证了顶点间的路径是最短的。

图的实现策略

  • 邻接矩阵:

  • 对于图的构造我们有三种方法,第一种 邻接矩阵,第二种 邻接表,第三种 十字链表。在这里我们深度解析 邻接矩阵与邻接表 的构造方法!首先我们阐述第一种方法: 邻接矩阵 (邻接矩阵用于相对来说比较稠密的无向图)例如此无向图:

相对应的邻接矩阵表示如下:

#include<iostream>
#include<string>
#define maxSize 10
using namespace std;
//在此声明 不用template 模板
class Graph{
public:
Graph(string str[],int vertex,int arc1);
~Graph(){
//由于没有动态申请内存 无法对改内存进行释放(在此处做声明)
cout<<"析构函数调用成功!";
};
void DFS(int v); //深度优先遍历
void FdgDFS(int v); //非递归的深度优先遍历
void BFS(int v); //广度优先遍历
private:
int verNum;
int arcNum;
string verName[maxSize];
//对于邻接矩阵构造无向图肯定少不了邻接矩阵 即二维数组
int arc[maxSize][maxSize];
//遍历时,对于没有访问过的顶点,需要建立flag 标识
int visited[maxSize]={0};
};
Graph::Graph(string str[],int vertex,int arc1){
verNum=vertex;
//顶点的赋值
for(int i=0;i<verNum;i++){
verName[i]=str[i];
}
for(int i=0;i<verNum;i++) //初始化邻接矩阵
for(int j=0;j<verNum;j++)
arc[i][j]=arc[j][i]=0;
//对边进行构造 输入依附于边的邻接点的下标
arcNum=arc1;
for(int k=0;k<arcNum;k++){
int i=0;
int j=0;
cout<<"请输入依附于边的邻接点下标 "<<endl;
cin>>i>>j;
//无向图的邻接矩阵是对称的
arc[i][j]=arc[j][i]=1;
}
}
//递归的深度遍历
void Graph::DFS(int v){
cout<<verName[v];
visited[v]=1;
for(int j=0;j<verNum;j++){
if(arc[v][j]==1 && visited[j]==0)
DFS(j);
}
}
//非递归的深度优先遍历
void Graph::FdgDFS(int v){
int Stack[maxSize];
int top=-1;
cout<<verName[v];
visited[v]=1;
Stack[++top]=v;
while(top!=-1){
v=Stack[top];
for(int j=0;j<verNum;j++){
if(arc[v][j]==1 && visited[j]==0){
cout<<verName[j];
visited[j]=1;
Stack[++top]=j;
break;
}
if(j==verNum-1)
top--;
}
}
}
//广度优先遍历
void Graph::BFS(int v){
//定义队列进行遍历
int Queue[maxSize];
int front=-1;
int rear=-1;
cout<<verName[v];
visited[v]=1;
Queue[++rear]=v;
while(front!=rear){
//出队
v=Queue[++front];
for(int j=0;j<verNum;j++)
if(arc[v][j]==1 && visited[j]==0){
cout<<verName[j];
visited[j]=1;
//入队
Queue[++rear]=j;
}
}
}
int main(){
string mystr[4]={"v0","v1","v2","v3"};
Graph myGraph(mystr,4,4);
//深度优先遍历
myGraph.DFS(2);
//非递归深度优先遍历
myGraph.FdgDFS(2);
//广度优先遍历
myGraph.BFS(2);
return 0;
}

教材学习中的问题和解决过程

  • 问题1:问题是有向图和无向图的广度遍历的区别
  • 问题1解决方案:根据我查的资料显示是不一样的,但是再向图中从出发的顶点没有路径的顶点也要写出来,这不是找所有的路径而是遍历所以不能漏掉任何一个元素。

我看到一个大佬的博客解决了这个问题,而且我阅读之后也有了比较深刻的理解

大佬的博客————图的深度优先遍历和广度优先遍历理解

代码调试中的问题和解决过程

  • 问题1:先是在用邻接矩阵实现无向图的补全,前面的都一切OK,该输出的基本上都输出了,但是在最后出现了一个空指针问题

  • 问题1解决方案:之后发现,是当时写程序的时候不够严谨,结果这个变量为空的,但是我当时没有去注意就直接使用,就出现NullPointException。
  • 问题2:在实现pp15.1的时候,出现了一个数组越界异常,这就没道理了啊

  • 问题2解决方案:不断往上追溯,最后发现好像是之前的一个类里面的遗留问题,当时没注意到,这个类的在这里被使用就出问题了

代码托管

上周考试错题总结

这两道题改了选项,我当时没注意到群里面的,好气哦

结对及互评

  • 20172324曾程
  • 博客中值得学习的或问题:
    • 书上代码的学习很到位
    • 代码调试环节比较详细,从截图上来看注释也很规范整齐,值得学习。
  • 基于评分标准,我给本博客打分:11分。得分情况如下:
    • 正确使用Markdown语法(加1分)
    • 模板中的要素齐全(加1分)
    • 教材学习中的问题和解决过程, 加4分
    • 代码调试中的问题和解决过程, 加4分
    • 本周有效代码超过300分行,加2分
    • 进度条中记录学习时间与改进情况的加1分

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积)
目标 5000行 30篇 400小时
第一周 0/0 1/1 8/8
第二周 671/671 1/2 17/25
第三周 345/1016 1/3 15/40
第四周 405/1421 2/5 23/63
第五周 1202/2623 1/5 20/83
第六周 1741/4364 1/6 20/103
第七周 400/4764 1/7 20/123
第八周 521/5285 2/9 24/147
第九周 1622/6907 2/11 17/164

参考资料

2018-2019-20172321 《Java软件结构与数据结构》第九周学习总结的更多相关文章

  1. 20172328 2018—2019《Java软件结构与数据结构》第二周学习总结

    20172328 2018-2019<Java软件结构与数据结构>第二周学习总结 概述 Generalization 本周学习了第三章集合概述--栈和第四章链式结构--栈.主要讨论了集合以 ...

  2. 《JAVA程序设计》_第九周学习总结

    一.学习内容 1.数据库的建立.配置 在官网先下载好MySQL.navicat for MySQL.XAMPP.MySQL-connecter 在XAMPP中点击start开启MySQL 在navic ...

  3. 20172328 2018-2019《Java软件结构与数据结构》第九周学习总结

    20172328 2018-2019<Java软件结构与数据结构>第九周学习总结 概述 Generalization 本周学习了无向图.有向图.带权图.常用的图算法.图的实现策略. 教材学 ...

  4. 2018-2019-20172329 《Java软件结构与数据结构》第九周学习总结

    2018-2019-20172329 <Java软件结构与数据结构>第九周学习总结 教材学习内容总结 <Java软件结构与数据结构>第十五章-图 一.图及无向图 1.图的相关概 ...

  5. 20172305 2018-2019-1 《Java软件结构与数据结构》第九周学习总结

    20172305 2018-2019-1 <Java软件结构与数据结构>第九周学习总结 教材学习内容总结 本周内容主要为书第十五章内容: 图(结点和结点之间的连接构成) 顶点:结点 边:结 ...

  6. 20172321 2018-2019《Java软件结构与数据结构》第三周学习总结

    教材学习内容总结 第五章 5.1概述 队列是一种线性集合,其元素从一端加入,从另一端删除:队列的处理方式是先进先出(First in First out). 与栈的比较(LIFO) 栈是一端操作,先进 ...

  7. 20172328 2018-2019《Java软件结构与数据结构》第五周学习总结

    20172328 2018-2019<Java软件结构与数据结构>第五周学习总结 概述 Generalization 本周学习了第九章:排序与查找,主要包括线性查找和二分查找算法和几种排序 ...

  8. 20172302 《Java软件结构与数据结构》实验三:查找与排序实验报告

    课程:<Java软件结构与数据结构> 班级: 1723 姓名: 侯泽洋 学号:20172302 实验教师:王志强老师 实验日期:2018年11月19日 必修/选修: 必修 实验内容 (1) ...

  9. 20172302 《Java软件结构与数据结构》实验二:树实验报告

    课程:<Java软件结构与数据结构> 班级: 1723 姓名: 侯泽洋 学号:20172302 实验教师:王志强老师 实验日期:2018年11月5日 必修/选修: 必修 实验内容 (1)参 ...

随机推荐

  1. MVC view操作(Razor语法)

    Razor,很有意思的剃刀.相较与之前开发WEB的方式,Razor真是轻松惬意. 下面说一下我使用Razor的一些心得. 页面中归根结底是一个输出字符串(HTML CSS JS等混合的字符串)的过程. ...

  2. Debian 8 安装 Qt5 和 go-qml

    一.安装相关依赖 ~ ᐅ sudo apt-get install build-essential libgl1-mesa-dev ~ ᐅ sudo apt-get install qt5-defau ...

  3. html5的拖拽事件

    原生拖放 一.若要一个元素可以被拖放,首先要为元素添加draggable属性 true 可以被拖放 false 不可以被拖放 auto 除img或url以外都可以被拖放 其他值 都不可以被拖放 注释: ...

  4. ThinkPhp5学习之新手博客

    前端框架来源网络,后端框架采用 ThinkPhp 5 开发 参考资料:哔哩哔哩  ThinkPHP5.1新手博客项目实战 项目地址:https://github.com/yjy1/tp5

  5. 关于java8(Stream)的一些用法

    如果要处理int[] 转换成 List<Integer>这种形式的,可以用下面这个方法: List<Integer> orgIds = Arrays.stream(reqVo. ...

  6. Apache 流框架 Flink,Spark Streaming,Storm对比分析(二)

    本文由  网易云发布. 本文内容接上一篇Apache 流框架 Flink,Spark Streaming,Storm对比分析(一) 2.Spark Streaming架构及特性分析 2.1 基本架构 ...

  7. 达梦数据库DM7小结

    除了很多主流的数据库,我们很熟悉之外,越来越多的国产数据库也涌现出来. 这次就小结一些有关武汉的达梦数据库7这个开发版数据库的有别或者需要注意的地方进行一个简单备注吧. 1.第一件大事就是下载.数据库 ...

  8. 2017-2018-1 20155232 《信息安全系统设计基础》第十周课堂测试(ch06)补交

    # 2017-2018-1 20155232 <信息安全系统设计基础>第十周课堂测试(ch06)补交 上课时完成测试后在提交的时候,没有提交成功,进行补交. 1.下面代码中,对数组x填充后 ...

  9. 2015306 白皎 《网络攻防》Exp3 免杀原理与实践

    2015306 白皎 <网络攻防>Exp3 免杀原理与实践 一.实践基础 免杀,故名思义,指的是一种能使病毒木马免于被杀毒软件查杀的技术. 免杀的方法有很多,比如加壳改壳.加垃圾指令.以及 ...

  10. python基础学习1-类相关内置函数

    #!/usr/bin/env python # -*- coding:utf-8 -*- #===issubclass(class,classinfo) 检查class是否是classinfo类的子类 ...