在JavaSE阶段,我们学习了I/O流,既然I/O流如此强大,那么能否跨越不同的主机进行I/O操作呢?这就要提到Java的网络编程了。 计算机网络基础 利用通信线路和通信设备,将地理位置不同的、功能独立的多台计算机互连起来,以功能完善的网络软件来实现资源共享和信息传递,就构成了计算机网络系统。 通过将我们的设备连接到路由器,来实现对互联网的访问。 我们的路由器连接在互联网上,而我们的设备又连接了路由器,这样我们的设备就可以通过路由器访问到互联网了。 通过网络,我们可以直接访问互联网上的另一台主机,比如我们要把QQ的消息发送给我们的朋友,或是通过远程桌面管理来操作另一台电脑,也可以是连接本地
什么是爬虫 爬虫爬的好,牢饭吃的早。但本身来讲数据是无罪的,爬虫作为一个便携且低成本获取数据的方式,现如今非常广泛,但还是要遵纪守法的,有些东西不该你知道就别动。 还要记住,爬虫的请求数量和频率不能过高,要不然和DDoS攻击没什么区别了。如果网站本身有反爬机制,那就别去强行突破了。 我们可以通过查看网站的robots.txt文件,了解可爬取的网页路径范围,这个文件会指明哪些网站会允许被爬取,哪些不允许被爬取。 爬虫的流程 爬虫的流程可能比你想象中的更简单 第一步:获取网页内容 我们会通过代码给一个网站服务器发送请求,它会返回给我们网页上的内容。 在我们平时使用浏览器访问网页内容时,本
首先给个爸爸像儿子的爆论,经过学习Python基础后,Python简直就是Gds 开端 python解释器 在第一次写下python代码之前,我们需要了解到python是通过解释器来解释成计算机语言的,这与某些语言的编译器有些许差别,所以我们需要下载python解释器来执行。 而python的运行过程是翻译一行,执行一行 我们一般说安装python,本质就是安装python解释器 python代码编辑器 我们这边使用的是PyCharm编辑器,当我们创建好项目后,需要熟悉以下东西 venv 表示这个项目独立的Python虚拟环境,可以让不同项目可以用不同的解释器版本,还有安装第三方库
冒泡排序 原理 冒泡排序在C语言程序设计篇已经讲解过了,冒泡排序的核心就是交换,通过不断地进行交换,一点一点将大的元素推向一端,每一轮都会有一个最大的元素排到对应的位置上,最后形成有序。算法演示网站:点我打开♪(∇*) 设数组长度为N,详细过程为: 共进行N轮排序。 每一轮排序从数组的最左边开始,两两元素进行比较,如果左边元素大于右边的元素,那么就交换两个元素的位置,否则不变。 每轮排序都会将剩余元素中最大的一个推到最右边,下次排序就不再考虑这些已经在对应位置的元素。 比如下面的数组: 那么在第一轮排序时,首先比较前两个元素: 我们发现前者更大,那么此时就需要交换,交换之后,继续向
生成树 极小连通图 我们来讨论一下极小连通子图。这里的极小主要是说的边数的极小,首先依然要是原图的子图并且是连通的,但是此时要求具有最大的顶点数和最小的边数,也就是说再去掉任意一条边会导致图不连通(直接理解为极大连通子图尽可能去掉能去掉的边就行了) 针对于极小连通子图,我们一般只讨论无向图我们依然将原图就是连通图和原图不是连通图分开分析,首先是原图本身就是连通图的情况: 原图本身就是连通图,那么其极大连通子图就是其本身,此时我们需要尽可能去掉那些“不必要”的边,依然能够保证其是连通的,也就是极小连通子图。可以看到右边两幅图,跟左边这幅图包含了同样的顶点数量,但是边数被去掉了一些,并且如果
实际上就是我们在一个复杂的地图中寻找一条能够从起点到达终点的路径。可以看到从起点开始,每到一个路口,可能都会出现多个分叉,可能有的分叉就会走进死胡同,有的分叉就会走到下一个路口。 那么我们人脑是怎么去寻找到正确的路径呢? 我们首先还是会从起点开始看,我们会尝试去走分叉路的每一个方向,如果遇到死胡同,那么我们就退回到上一个路口,再去尝试其他方向,直到能一直往下走为止。经过不断重复上述的操作,最后我们就肯定能够到达迷宫的出口了。 而图的搜索,实际上也是类似于迷宫这样的形式,我们需要从图的某一个顶点出发,去寻找到图中对应顶点的位置,这一部分,我们将对图的搜索算法进行讨论。 深度优先搜索(DFS
前面我们介绍了图的一些基本概念,我们接着来看如何在程序中对图结构进行表示,这一部分可能会涉及到某些在《线性代数》这门课程中出现的概念。 邻接矩阵 有向图邻接矩阵 邻接矩阵实际上就是用矩阵去表示图中各顶点之间的邻接关系和权值。假设有一个图 $G=(V,E)$,其中有N个顶点,那么我们就可以使用一个N×N的矩阵来表示,比如下面有A、B、C、D四个顶点的图: 此时我们需要使用邻接矩阵来表示它,就像下面这样: 对于一个不带权值的图来说: $$G_{ij} = \begin{cases} 1, & \text{无向图的 } (v_i, v_j) \text{ 或有向图
地图盘根错节,错综复杂,不同的道路相互连接,我们可以自由地从这些道路通过,从一个地点到达另一个地点。当然除了地图,我们的计算机网络、你的人际关系网等等,这些都可以用图结构来表示。 图也是由多个结点连接而成的,但是一个结点可以同时连接多个其他结点,多个结点也可以同时指向一个结点,跟我们之前讲解的树结构不同,它是一种多对多的关系: 它比树形结构更加复杂,没有明确的层次关系,结点与结点之间的连接关系更加自由,图结构是任意两个数据对象之间都有可能存在某种特定关系的数据结构。 基本概念 图(Graph)一般由两个集合共同构成,一个是非空但是有限的顶点集合V(Vertex),另一个是描述顶点之间连接关
什么是哈希冲突 前面我介绍了哈希函数,通过哈希函数计算得到一个目标的哈希值,但是在某些情况下,哈希值可能会出现相同的情况: 这种情况,我们称为哈希碰撞(哈希冲突) 这种情况是不可避免的,我们只能通过使用更加高级的哈希函数来尽可能避免这种情况,但是无法完全避免。当然,如果要完全解决这种问题,我们还需要去寻找更好的方法。 线性探测法 我们可以选择退让,不去进行争抢,我们可以去找找哈希表中相邻的位置上有没有为空的,只要哈希表没装满,那么我们肯定是可以找到位置装下这个元素的,这种类型的解决方案我们统称为线性探测法 既然第一次发生了哈希冲突,那么我们就继续去找下一个空位: $$h_i(\text{
我们之前认识的查找算法,最快可以达到对数阶 $O(logN)二分$,那么我们能否追求极致,让查找性能突破到常数阶呢?这里就要介绍到我们的散列(也可以叫哈希 Hash)它采用直接寻址的方式,在理想情况下,查找的时间复杂度可以达到常数阶 $O(1)$。 散列表也就是哈希表有什么用 散列(Hashing)通过散列函数(哈希函数)将要参与检索的数据与散列值(哈希值)关联起来,生成一种便于搜索的数据结构,我们称其为散列表(哈希表),也就是说,现在我们需要将一堆数据保存起来,这些数据会通过哈希函数进行计算,得到与其对应的哈希值,当我们下次需要查找这些数据时,只需要再次计算哈希值就能快速找到对应的元素了: