【Golang系统开发】搜索引擎(1) 如何快速判断网页是否已经被爬取
文章目录
- 1. 写在前面
- 2. 数组存储
- 3. 位图存储
- 3.1 位图简介
- 3.2 链表法
- 3.3 开放寻址法
1. 写在前面
在实际工作中,我们经常需要判断一个对象是否存在,比如判断用户注册登陆时候,需要判断用户是否存在,再比如搜索引擎中的爬虫,判断该网页是否已经爬过,减少一些重复的工作。
2. 数组存储
我们当然可以使用有序数组,二叉搜索树,哈希表等等来存储所有的用户id。但是无论是有序数组还是二叉搜索树,这两种数据结构都是基于二分查找的思想从中间元素开始查起的。所以在查询用户id是否存在时,这两种数据结构的检索时间都是 O(logn)。
而哈希表的检索时间是O(1)。因此如果我们希望能快速查询元素是否存在,那哈希表就是最合适的。但是哈希表中,我们还是需要计算哈希值来获取数组的下标,这也是需要耗费一定的时间。
那应该怎么做呢?
我们可以直接使用一个足够大的数组来存储用户id,如果该用户存在,就在该用户id的位置标识为 1 ,否则就是默认的 0 也就是不存在。但是这个也会有问题,如果我们的用户id范围很广,比如说是在10w之内,那我们就需要保证数组的长度是大于10w的,除此之外,如果这个数组是int类型的话,每个元素就会占据4/8个字节,用4/8个字节存储0和1是不是很浪费空间,所以这个方案比较消耗空间,典型的空间换时间。
那么我们怎么优化存储空间呢?接下来就介绍一下位图了。
3. 位图存储
3.1 位图简介
首先我们需要优化存储的数据结构,不是int,虽然char和bool类型都是1字节,相比较于4/8字节的int类型,已经提升了4/8倍了(32位的机器是4 byte,64位的机器是8 byte),但是其实用字节作为单位来存储一个flag类型也是很浪费的,flag类型的直接使用bit类型的就可以了。
如果我们使用bit类型来存储,就是原来的32倍了,非常亏贼!而这种以bit为单位构建数组的方案就叫做bitmap,也就是位图。
如果你在好奇这个32是怎么算的?我们原来是用一个int类型取表示是否存在这个值,我们假设是在32位的机子上,这个int类型就是4个byte。而我们现在用的是bit来作为存储运算,1 byte = 8 bit,所以就是原来的 1/4*8 ,就是1/32倍。

虽然位图相对于原始数组来说,在元素存储上已经有了很大的优化,但如果我们还想进一步优化存储空间,要怎么做呢?
其实有一个点很好想到,我们都知道一个数组的空间其实就是 数组元素的个数 * 每个元素大小,位图已经把我们每个元素的大小限定在最小单位的bit了,而我们存储元素的个数一定要大于我们所需要存储的用户id数的,这似乎已经无解了。但其实我们可以通过哈希算法将大于数组长度的用户id转化成一个小于数组长度的数值作为下标,除此之外, 使用哈希函数还可以使我们的用户id不需要是正整数,可以是字符串,因为字符串可以通过哈希函数的转换成正整数。
当然如果我们数组压缩到很小的时候,就容易发生哈希冲突,如果两个元素,A和B都映射到同一个地方了,那么就无法判断是A存在,还是B存在了,那应该如何解决哈希冲突呢?一般会有两种方法,开放寻址法,链表法
3.2 链表法
数组的每个成员是一个链表。该数据结构所容纳的所有元素均包含一个指针,用于元素间的链接。我们根据元素的自身特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。
先调用这个元素的 hash 方法,然后根据所得到的值计算出元素应该在数组的位置。如果这个位置上没有元素,那么直接将它存储在这个位置上;如果这个位置上已经有元素了,那么与新元素进行比较:相同的话就不存了,否则,将其存在这个位置对应的链表中。

3.3 开放寻址法
当发生哈希冲突时,重新找到空闲的位置,然后插入元素。寻址方式有多种,常用的有线性寻址、二次方寻址、双重哈希寻址等等
线性寻址就是如果冲突了,就从冲突位置线性顺序向下继续寻找空位置。

二次寻址就是每次向上找两格,冲突就向下找两格,再冲突就是向上找四个,-2,+2,-4,+4这样的上下的找,直到找到不冲突为止。
双重哈希寻址就是使用多个hash函数获取多个哈希值。 而这种方法也称为双散列。可以使用两个哈希寻址,也可以使用多个哈希来寻址,那这是不是就有点像布隆过滤器。在布隆过滤器中,如果我们对一个对象,使用来N个哈希函数,就会得到N个值,也就是N个下标,我们会把数组中对应下标位置都变成1。
而布隆过滤器和位图最大的区别就是我们不再使用一位来表示一个对象,而是使用N位来表示一个对象。这样两个对象的N位都相同的概率就会大大降低了,就能大大缓解哈希冲突了。

而N个哈希都冲突的情况也是会有的,或者说刚好是下面这种Z的情况

那么我们就当这个Z是已经存在了,让用户重新输入就好了,因为在大多数系统中,我们并不要求100%的准确,我们只要保证用户体验就行了,这种方案已经是权衡很多之后才确定是最优解了。
这个X,Y,Z其实就是我们的网址。这样我们就可以快速判断网页是否已经被爬取了。
还有一种位图的优化:Roaring Bitmap 后续在合并多个postingsList会有作用。
相关文章:
【Golang系统开发】搜索引擎(1) 如何快速判断网页是否已经被爬取
文章目录 1. 写在前面2. 数组存储3. 位图存储3.1 位图简介3.2 链表法3.3 开放寻址法 1. 写在前面 在实际工作中,我们经常需要判断一个对象是否存在,比如判断用户注册登陆时候,需要判断用户是否存在,再比如搜索引擎中的爬虫&#x…...
记录--一个好用的轮子 turn.js 实现仿真翻书的效果
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 国际惯例,官网链接 官网传送门 Github地址 github上有几个demos例子,介绍了基础用法。 我参考官网的例子,写了一个demo示例 安装 turn.js 依赖 jquery 库࿰…...
《Spring Boot源码解读与原理分析》书籍推荐
Spring Boot是目前Java EE开发中颇受欢迎的框架之一。依托于底层Spring Framework的基础支撑,以及完善强大的特性设计,Spring Boot已成为业界流行的应用和微服务开发基础框架。 《Spring Boot源码解读与原理分析》共14章,分为4个部分。第一部…...
C++ 什么时候使用 vector、list、以及 deque?
如果需要高效地快速访问(随即存取),并且不在乎插入和删除的效率,使用 vector 如果需要大量的插入和删除,而且不关心快速访问 (随即存取) ,使用 list 如果需要快速访问 (随即存取) ,并且关心两端数据插入和删除&#…...
视频创作者福音,蝰蛇峡谷NUC12SNKI7视频剪辑测评
英特尔NUC绝对是PC市场里最为特殊的产品,相比众多OEM设计制造的台式机而言,英特尔NUC主打小体积、高度集成化、强扩展性以及尽可能优异的性能表现。尤其是在主打游戏体验的NUC产品出现之后,更是将极致体验演绎到了极致。 在搭载独显的幻影峡谷…...
使用Qt中的QDir类进行目录操作
文章目录 概述QDir类的基本功能获取当前目录创建目录列出目录内容筛选目录内容筛选特定命名文件 复制文件和目录删除文件和目录更改文件名 应用场景总结 概述 Qt是一个跨平台的C应用程序开发框架,其中提供了许多方便的类来处理文件和目录操作。其中,QDi…...
qt服务器 网络聊天室
widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化空间server new QTcpServer(this); }Widget::~Widget() {delete ui; }//启动…...
meanshift算法通俗讲解【meanshift实例展示】
meanshift算法原理 meanshift算法的原理很简单。假设你有一堆点集,还有一个小的窗口,这个窗口可能是圆形的,现在你可能要移动这个窗口到点集密度最大的区域当中。 如下图: 最开始的窗口是蓝色圆环的区域,命名为C1。蓝…...
正交变换和仿射变换
正交变换和仿射变换 平面的正交变换 正交点变换(保距变换) 平面上的一个保持任意两点距离不变的点变换 平面正交变换性质 正交变换的乘积是正交变换恒等变换是正交变换正交变换将(不)共线的三点映射成(不)…...
Electron 多端通信桥 MessageChannelMain和 MessagePortMain 坑点汇集
简介 MessageChannelMain 是 DOM MessageChannel 对象的主进程等价对象。 它的特有功能是创建一对已连接的 MessagePortMain 对象。 Electron 本身为了灵活追加 on("message") 机制,就说明该 MessageChannelMain 已经被创建了,而 Web 开发中&a…...
Html5播放器按钮在移动端变小的问题解决方法
Html5播放器按钮在移动端变小的问题解决方法 用手机浏览器打开酷播云视频,有时会出现播放器按钮太小的情况,此时只需在<head>中加入下面这段代码即可解决: <meta name"viewport" content"widthdevice-width, initia…...
Rust 开发环境搭建【一】
Rust 开发环境 推荐 搭建: 安装 rust 语言 以及 工具链 推荐安装方法:rustup curl --proto ‘https’ --tlsv1.2 -sSf https://sh.rustup.rs | sh 在国内如果访问速度慢,可以使用清华大学提供的镜像服务: https://mirrors.tu…...
C# Blazor 学习笔记(3):路由管理
文章目录 前言路由管理App.razor设置登录页面设置空布局 前言 我们知道使用Blazor的官方模板,我们会自动得到一个拥有侧边栏的布局页面。但是我们发现我们所有新建的页面都有侧边栏。有时候我们需要跳出这个布局,比如我要做登录页面的时候,我…...
int[]数组转Integer[]、List、Map「结合leetcode:第414题 第三大的数、第169题 多数元素 介绍」
文章目录 1、int[ ] 转 Integer[ ]:2、两道leetcode题遇到的场景:2.1、int[ ] 转 List<Integer> :2.2、int[ ] 转 Map: 1、int[ ] 转 Integer[ ]: public static void main(String[] args) {int[] nums {1, 2, 3}; Integer[] array Arrays.stream(nums).boxed().to…...
vue子传父的一种新方法:this.$emit(‘input‘, value)可实现实时向父组件传值
今天要说的就是利用v-model和this.$emit(‘input’,value)实现子传父。 众所周知,v-model是给input绑定,方便对表单的双向绑定。 其实,v-model是个语法糖,具体案例如下所示。 <input v-model"inputValue">相当于…...
【Web】web
dns与域名 网络是基于tcp/ip协议进行通信和连接的 应用层——传输层——网络层——数据链路层——物理层 每一定的台主机都有一个唯一且固定的地址标识——IP地址 IP地址的做用:1.区分用户和计算机;2.进行通信 IP地址由32位二进制数组成,…...
css中的bfc是什么?
什么bfc? BFC(Block Formatting Context)块级 格式化 上下文。 BFC就是页面上的一个隔离的独立盒子,容器里面的子元素和外面的元素不会相互影响。 为什么要bfc? bfc是我们去主动触发的,并不是自动就存在的,它是帮助我们解决cs…...
【前端知识】React 基础巩固(四十四)——其他Hooks(useContext、useReducer、useCallback)
React 基础巩固(四十四)——其他Hooks(useContext、useReducer、useCallback) 一、useContext的使用 在类组件开发时,我们通过 类名.contextType MyContext的方式,在类中获取context,多个Context或者在函数式组件中…...
华为云hcip核心知识笔记(数据库服务规划)
华为云hcip核心知识笔记(数据库服务规划) 1.云数据接库优势 1.1云数据库优点有: 易用性强:能欧快速部署和运行 高扩展:开放式架构和云计算存储分离 低成本:按需使用,成本更加低廉 2.云数据库r…...
【有趣的】关于Map的一些小测试
Map在代码中用到得非常多,它是无序的、key-value结构的,其读取会非常快。 今天看了个小文章Map判空 、空字符串、空key值等各种判断方法,你都掌握了吗?便自己也玩一下。 一、判空 因为对象已经new出来了,所以map指向的…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
