何为堆 一个数组序列我们可以将其用完全二叉树或近似完全二叉树(不是满二叉树的完全二叉树)表示出来,当数组下标为i时,它的父节点为(i-1)/2,左孩子为(2i+1),右孩子为(2i+2),这种对应关系说明数组下标为0的地方也要存储数据。(关于完全二叉树和满二叉树我在这里不做介绍) 堆是在完全二叉树的基础上递归定义的,堆分为大顶堆和小顶堆。 大顶堆:根节点的数值大于孩子节点,完全二叉树的左右子树同时满足这个条件。 小顶堆:根节点的数值小于孩子节点,完全二叉树的左右子树同时满足这个条件。 从这种数据结构中我们可以发现:大顶堆的根节点也就是数组的第一个元素必定是最大值,而小顶堆必定是最小值,看到这,我想大家已经大概能感觉的到堆这种数据结构为什么可以用来排序了。 在来看个大顶堆和小顶堆的图解吧: 堆排序的过程 要想写出堆排序的代码,首先我们一定要清楚堆排序的过程,根据堆这种数据结构的特性,我总结了一下堆排序的过程: 首先我们需要将一个数组初始化为堆 在初始化堆的过程中我们必定要移动数组中元素的位置 初始化完 继续阅读 >>


董恒毅 17/07/27 20:25:04
快速排序实现代码:快速排序 可以看到我的代码有一个错误版,我在这里给大家分析一下为什么会出现错误,并且将之记录以便今后进行查阅。 快速排序(错误版分析) int Quick :: process(int array[], int l, int r) { int temp = array[l]; while(l != r) { while(array[r] >= temp) r--; array[l] = array[r]; l++; while(array[l] <= temp) l++; array[r] = array[l]; r--; } array[l] = temp; return l; } 如上是我自己实现的单趟快速排序。 快排的算法思想 从待排序列中任意选择一个记录,以该记录为关键字,凡数组中元素小于该关键字的都移动至该关键字前面,反之移动到后面。致使一趟快速排序之后,以关 继续阅读 >>


董恒毅 17/07/22 00:20:16
理解归并 一接触算法,我就觉得自己应该去转行,一个归并排序可以说是实现了一整天,从看书到整理思路,看书上的代码,然后再根据自己的思想写一遍,感觉其中的过程是如此艰难,而且还是在参照书本的前提下进行的学习,真心好累。。。 不过功夫不负有心人,总算是将自顶向下的归并排序实现出来了,我觉得归并排序最大的难点就在于两次递归,要理清这个思路是比较复杂的,我就将自己学习归并排序的艰难路程记录下来,供大家参考学习。 首先我们需要理解什么是归并,假设我们现在已经有两个有序的数组,现在要将两个有序的数组合并为一个大的依旧有序的数组,这个过程就叫做归并,也是归并排序所要求的最基础的操作。我们来看一下这个归并的实现代码:(这个代码的实现还是很简单的) #include<iostream> using namespace std; #define SIZE 10 int main() { int array[SIZE]; //辅助数组 int array_result[SIZE]; int mid = SIZE/2; i 继续阅读 >>


董恒毅 17/07/21 15:04:15
设定防火墙开放指定端口 由于自己的腾讯云突然无法访问8080端口,在网上查阅了相关资料之后发现是防火墙的问题,因为Centos 7防火墙默认是不开放任何端口的,所以我们要对防火墙进行设置。 Centos 7 不在使用以前的iptables,而是对防火墙进行了加强,现在使用的是firewalld,它的位置在/usr/lib/firewalld(系统配置)和/etc/firewalld(用户配置)都有相关设置,并不建议修改/usr/lib/firewalld因为这是系统配置。 现在我们要开启8080端口,只要运行以下命令就可以了: 1.查看已开放的端口(默认不开放任何端口) firewall-cmd --list-ports 2.开启8080端口 firewall-cmd --zone=public(作用域) --add-port=8080/tcp(端口和访问类型) --permanent(永久生效) 3.重启防火墙 firewall-cmd --reload 4.移除指定端口 firewall-cmd --zone= public --remo 继续阅读 >>


董恒毅 17/07/10 11:34:15
在开始说正事之前我先给大家介绍一下这份代码的背景,以免大家有一种雾里看花的感觉。在本系列的前几篇博客中有一篇是用多线程进行百度图片的抓取,但是当时使用的多线程是非常粗略的,只是开了几个线程让抓取的速度提升了一些(其实提升了很多),初步的使用了一下线程,这篇博客将线程的使用进行了一些深入。 博主最近准备学习分布式网络爬虫,鉴于手头资料太少,所以如果有这方面的爱好者欢迎大家共同交流与学习。 项目背景 博主这次的需求是抓取一些淘宝的数据,在还没有开始学习分布式之前,我们需要掌握基本的并行爬虫的相关知识。在这里我要先吐槽一下《自己动手写网络爬虫》这本书,不得不说,这本书让我认识到了什么叫做:有一本好书,真的会提升很多学习的效率。反正这本书不适合入门,而且非常的老,代码都不能用!!但其中还是有一些值得学习的思想,但。。。不说了,都是泪。。。 本次代码仍有很多不完善的地方,比如并没有用到线程池,然后只是给大家提供一种思路,代码并不完善,博主也在不断学习当中,不得不说Java网络爬虫的学习曲线还是很陡峭的,但我认为需要开发一个好爬虫是需要语言功底很扎实的,所 继续阅读 >>


董恒毅 17/06/14 15:04:26
代码思想主要是广度优先搜索,有不了解的同学可以下去了解一下算法思想,我们直接来看代码: redis数据库爬虫队列代码: package redisqueue; import redis.clients.jedis.Jedis; /** * Created by hg_yi on 17-6-12. */ public class RedisQueue { private Jedis jedis = null; //本地redis数据库链接服务 public RedisQueue() { //连接本地的 Redis 服务 jedis = new Jedis("127.0.0.1", 6379); //权限认证 jedis.auth("******"); } //将未访问的url加入到toVisit表中(使用的是尾插法) public void addToVisit(String url) { jedis.rpush("to 继续阅读 >>


董恒毅 17/06/12 20:48:40
注:本篇博客的所有测试环境均为Ubuntu16.04之下,本篇博客总结自Redis教程。 数据库的安装与配置 Ubuntu下安装 $sudo apt-get update $sudo apt-get install redis-server 服务端启动命令 redis-server 客户端启动命令 redis-cli 启动成功之后会出现: redis 127.0.0.1:6379> 在终端上输入ping命令,如果出现pong则说明安装成功。 设置redis数据库可远程登录并设置登录密码 使用root权限修改/etc/redis/redis.conf文件: 想使用哪个密码进行登录就直接修改“password”这个字符串就行,如图我现在的密码是password。 设置允许远程登录: 将bind 127.0.0.1那一行进行注释。 修改完之后将redis服务进行重启: sudo /etc/init.d/redis-server r 继续阅读 >>


董恒毅 17/06/07 20:32:02
简介布隆过滤器 当我们要对海量url进行抓取的时候,我们常常关心一件事,就是url的去重问题,对已经抓取过的url我们不需要在进行重新抓取。在进行url去重的时候,我们的基本思路是将拿到的url与已经抓取过的url队列进行比对,看当前url是否在此队列中,如果在已抓取过的队列中,则将此url进行舍弃,如果没有在,则对此url进行抓取。看到这,如果有哈希表基础的同学,很自然的就会想到那么如果用哈希表对url进行存储管理的话,那么我们对于url去重直接使用HashSet进行url存储不就行了,事实上,在url非海量的情况下,这的确是一种很不错的方法,但哈希表的缺点很明显:费存储空间。 举个例子: 对于像Gmail那样公众电子邮件提供商来说,总是需要过滤掉来自发送垃圾邮件的人和来及邮件的E-mail地址。然而全世界少说也有几十亿个发垃圾邮件的地址,将他们都存储起来需要大量的网络服务器。如果用哈希表,每存储一亿个E-mail地址,就需要1.6GB的内存(用哈希表实现的具体实现方式是将每一个E-mail地址对应成一个八字节的信息指纹,然后将这个信息存储哈希表,但是 继续阅读 >>


董恒毅 17/06/06 19:40:14
Servlet初始化过程、ServletConfig 每个Servlet都必须由Web容器读取Servlet设置的信息,初始化等,才能生成对应的Servlet实例。对于每个Servlet的设置信息,Web容器都会为其生成一个ServletConfig作为代表对象。 在Servlet接口上,定义了与Servlet生命周期及请求服务相关的init,service,destroy三个方法。每一次请求来到容器时,会产生HttpServletRequest,HttpServletResponse对象,并调用service方法时当做参数传入。 在Web容器启动后,根据上面所说,会产生一个ServletConfig对象,而后调用init方法并将产生的ServletConfig对象传入其中,这个过程在创建Servlet实例之后只会发生一次,之后每次请求到来,就只调用Servlet的service方法进行服务。 Servlet类架构图: 在Java中,当我们想要在对象实例化后做一些操作,必须定义构造器,然而在JavaWeb中则不然,当我们想要使用ServletCo 继续阅读 >>


董恒毅 17/06/05 21:55:02
平常我们在浏览网页的时候,会有一些网站要求我们进行登录,当我们成功登录之后,会发现我们所浏览的所有相关网页都不再需要我们重新登录,这是为什么呢。还有当我们在电商平台进行购物的时候,我们虽然是在同一家电商平台进行购物,但是我们明明是在不同的页面进行的添加购物车的选项,为什么最后我们可以在购物车中找到我们所添加的所有商品呢。其实,这些都是我们在Web后台方面使用了Cookie技术。 Cookie简介 Cookie定义:Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。 session:会话,指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间。具体到Web中的Session指的就是用户在浏览某个网站时,从进入网站到关闭浏览器所经过的这段时间,也就是用户浏览这个网站所花费的时间。(摘自百度百科) 实现思想 如何让网站记住我们,乃至记住我们之前做过的事情,我们可以联想,如果让服务器在我们进行此次请求的时候,可 继续阅读 >>


董恒毅 17/06/04 00:17:32