【C++】位图和布隆过滤器

位图和布隆过滤器

  • 前言
  • 正式开始
    • 位图
      • 位图讲解
      • 模拟实现位图
      • 几道关于位图的题目
    • 布隆过滤器
      • 概念
      • 实例
      • 布隆过滤器模拟实现
      • 误判率测试
      • 几道题

在这里插入图片描述

前言

本来本篇是和前面的两篇连着的,但是没写到一块,位图和布隆过滤器都是基于哈希的思想的,如果对于哈希不熟悉的同学可以看看前两篇(重点看第一篇):
【C++】模拟实现哈希(闭散列和开散列两种方式)

【C++】模拟实现unordered_map和unordered_set

正式开始

位图

先提个问题:现在有40亿个不重复的无符号整数,无序的,给你一个无符号整数,如何判断出该树是否在这40亿个数中?

各位有思路吗?

先算算40亿个无符号整数有多大吧,一个无符号整数4Byte,40亿个4Byte,也就是160亿Byte。看着不太方便,我们把它转成G来看。

一个G多少个Byte呢?1G = 1024MB = 1024 * 1024 KB = 1024 * 1024 * 1024 B,也就是 230 B。
那么1G大概就是10亿多B,我们就按照1G为10亿B来说的话,160亿B大概就是16G(实际比16G小一点)。16个G,内存中是绝对放不下的,所以就不要想着用set/unordered_set了。

那么该用啥呢?

就是马上要讲的位图。

位图讲解

其实我前面博客中讲Linux的时候已经提到过位图了,就在讲文件的那篇博客中,磁盘上的文件存储的时候就用到了位图。

那位图是干嘛的?
接着开始的问题,如果我们用一个bit位来表示一个数(0表示数不在,1表示数在),是否可行?
先来算算,用一个bit位表示一个数的话,总共40亿个数,那就是10多就是230,40亿就是232,那么就需要232个bit位。这是多大呢? 一个Byte有8个bit位,也就是23,那么232个bit位就是229个Byte,1G是230B,那么229个Byte就是0.5G,也就是512MB。

这样的话,内存完全是可以存下的。

那么如何记录某一个数呢?
也很简单,看图:
在这里插入图片描述
这就是位图。

前面哈希中讲了直接定址法 ==》不存在哈希冲突。
但主要讲了除留余数法 ==》存在哈希冲突

而这里的的位图用的是直接定制法,是不存在哈希冲突的,只要位图开得够大每个整数数都一定会有其固定的位置,因为整数是有范围的,0 ~ 42亿多,用232个bit位就能存放下所有的整数。

STL库中也是给了位图的,就叫做bitset,但是先不看STL库中的,下面我们就先模拟实现一下位图。

模拟实现位图

我们可以用顺序表来实现,顺序表中可以存储整形家族的元素,具体哪一种取决于你自己。

我这里直接用char了,char一个字节更方便一点,一个字节就是8bit位,存储232个bit的话,再除以四就是229个char。但我们这里实现的就先不给固定大小,万一数字个数不是这么多还可以改。

写到命名空间中,方便和库中的区分:
在这里插入图片描述

位图其实就只需要实现3个重要的接口,set、reset、test。
set是将数设置到位图中,也就是置一操作;reset就是将数从为图中去除,也就是置零操作;test就是检测某个数是否在位图当中。

但实现这三个接口之前,我们先要设置位图要开多大的空间。

我们可以给一个非类型模版参数:
在这里插入图片描述
N就是有多少个数。

假如说我们这里只需要开10个数,那么就要用10bit位来表示这十个数,如果存放的是char,一个char八个Byte,那么就需要开 10 / 8 + 1个char就够了。那如果开N个数,就需要 N/8 + 1就够了。可能有同学说,这样的话如果N是8的倍数,不就浪费了8个bit了吗?没关系,8个bit才多大,就一个char而已,浪费不了多少的。

那就要在构造函数中开空间:
在这里插入图片描述

然后再来写set,如果想要让一个数在位图的对应位置中设置为1,怎么搞呢?

看图:
在这里插入图片描述

表大小为16,如果想让第12个位置变为1。

可以让12 / 8得到的就是12在第i个char中,再让12%8得到的就是12在某个char中的第j个位置。
然后我们搞一个1,让1左移j位,然后和_bits[i]相或,就能让对应数的位置置为1。

在这里插入图片描述

再说reset,反过来,让_bits[i] &= ~(1<<j)即可,1 << j为对应数位置为1,然后取反,就是该数位置为0,剩余都为1,再&,就能让_bits中数的对应位置置为0。
在这里插入图片描述

test更简单,&后的结果是否为0,为零就不存在,不为零就存在。
在这里插入图片描述

测试一下:
在这里插入图片描述

调试看看:
在这里插入图片描述
上面8算后的就是第二个char最低位,9是第二个char的低2位,20是第3个char的第5位,所以对应的结果就是3(8和9在同一char中),16。

然后再来看我们最开始的问题。
用位图的话,就要开空间,40亿个数,以上面的逻辑,就会开232 / 23 + 1个char,也就是229 + 1
个char。

那么我们该怎么给N赋值呢?
两种方式,一种直接给-1,-1补码为全1,转成size_t就变成了232 - 1个数。230是10多亿,乘以4就是40多亿,所以这样就是40多亿个数。还有一种是0xffffffff,也是全1。

在这里插入图片描述
然后我这里没有40多亿个数,就不演示怎么搞了,但我可以开一下任务管理器看看程序运行起来占了多少内存:
在这里插入图片描述
就是512MB。

bitset还有其他接口,但这上面的几个最重要,其他的就不模拟实现了。

几道关于位图的题目

再来几个问题:

  1. 给定100亿个整数,设计算法找到只出现一次的整数?
  2. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
  3. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整

我们挨个来说。

给定100亿个整数,设计算法找到只出现一次的整数?

这里就要用位图了。但是和上面有点不一样,看题,100亿个整数,整数是有范围的:42亿多个数,题目中给100亿个数,那么就一定会有重复的数,所以说题中让我们找只出现一次的数。

我们把bitset改进一下,用两个bit位表示一个数就行了,00表示某个数没有出现,01表示某个数出现了一次,10表示某个数出现了两次以及两次以上。11就不用了。

但是用一个位图的话算起来稍微麻烦一点,我们可以用两个位图,一个表示某一个数的xx两位中的高位,一个用来表示xx两位中的低位:
在这里插入图片描述
如图中蓝色框位置,上面表示低位,下面表示高位(或者反过来)。

那么我们来模拟实现一下:
在这里插入图片描述
print_once_num就是打印一下出现一次的数。

再来看下一题:

给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?

还是位图,用两个个512MB的位图将两个文件中给的数统计一下,然后让后让两个位图对应位置相与,得到的结果就是交集。

位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整

这就是第一个问题的变种,用两个位表示一个数,00、01、10都有效11就表示超过两次的。不细说了。

我们再来看看STL库中的位图:
在这里插入图片描述
在这里插入图片描述

好多接口,但set、reset、test最有用。

位图优点就是非常快,而且节省空间。但是只能映射整数,这一点比较局限。

下面来说说布隆过滤器。

布隆过滤器

概念

将哈希与位图结合,即布隆过滤器。

位图可以用来查找整数在不在。
布隆过滤器还能用来查找字符串在不在。

前一篇博客中,模拟实现哈希里面就用到了字符串哈希算法,里面有BHDK方法来让字符串转换成一个下标位置。这里布隆过滤器就是用一下字符串哈希算法,然后将对应的数字转换成下标位置,对应到数组中即可。

来个例子:假如现在要记录一下几个公司的名称,比如百度、字节、 美团等等。
在这里插入图片描述

现在再登记一个B站,登记前要判断一下之前是否登记过了,假如B站和美团计算出来的位置重复了,那么就会导致误判:

在这里插入图片描述

这就是布隆过滤器的一个缺点,如果原字符串没登记,但是判断出在了就会导致误判,判断出不在才是准确的。

那这样就太坑了,怎样改改不让重复呢?

完全不重复是不太可能的,但是我们可以降低重复率。
可以采用多个字符串哈希函数,从而让每个字符串映射出多个不同的位置。比如说每个字符串映射三个位置:
在这里插入图片描述
这样就能降低误判率,让每个值多映射几个位,理论而言,一个值映射的位越多,误判的概率越低,但也不能映射太多,映射位越多,空间消耗越多。

实例

在来两个例子吧。

失信名单

假如说你接到了一个电话,而且是诈骗电话,怎样在你还未接到电话的时候就显示出其是一个诈骗电话?

一般来说,这些失信名单/诈骗分子电话信息都是存储在数据库中的,而数据库一般都是在本地磁盘上或远端的,如果直接去数据库中找,效率太低了,我们可以提前搞一个布隆过滤器。

如果布隆过滤器中显示当前号码为诈骗电话,再到数据库中确认就行。如果显示不是,那就一定不是。

这样做就能大大提升查找效率。

注册名称

我们进一个网站注册账号,注册账号时需要让我们输入昵称,怎样快速判断当前昵称是否重复了/违规了呢?

还是布隆过滤器,但是这里可以不用判断那么仔细。

如果你当前输入的昵称过滤后显示重复了,那么就直接提示你名称重复/违规了,需要重新输入,不需要再仔细比对了,因为换个昵称还是没那么费事的。如果没有提示重复/违规,那就定了。

这样也能提高查找效率,同时也允许误判。

STL库中并未提供布隆过滤器。

但是我们还是要模拟实现一下的。

布隆过滤器模拟实现

上面也说了,同一个字符串要经过不同的哈希函数映射出不同的下标位置的,那么就需要搞多个哈希函数了,我这里就直接用上一篇文章中的了:

这里用三个哈希函数:

struct HashBKDR
{
	// BKDR
	size_t operator()(const string& key)
	{
		size_t val = 0;
		for (auto ch : key)
		{
			val *= 131;
			val += ch;
		}

		return val;
	}
};

struct HashAP
{
	// BKDR
	size_t operator()(const string& key)
	{
		size_t hash = 0;
		for (size_t i = 0; i < key.size(); i++)
		{
			if ((i & 1) == 0)
			{
				hash ^= ((hash << 7) ^ key[i] ^ (hash >> 3));
			}
			else
			{
				hash ^= (~((hash << 11) ^ key[i] ^ (hash >> 5)));
			}
		}
		return hash;
	}
};

struct HashDJB
{
	// BKDR
	size_t operator()(const string& key)
	{
		size_t hash = 5381;
		for (auto ch : key)
		{
			hash += (hash << 5) + ch;
		}

		return hash;
	}
};

然后我们还需要确定布隆过滤器要开多大的空间。因为随着插入元素的增多,空间开小了就会导致误判率提高,空间开大了就会导致浪费。

这里有一篇文章,内部就讲了关于哈希函数个数、插入元素个数以及布隆过滤器大小之间的关系,感兴趣的同学看看:详解布隆过滤器的原理,使用场景和注意事项。

我这里就直接截取其中的内容来用了:
在这里插入图片描述
我也在上面图中标记了,如果我们想要用3个哈希函数,那么布隆过滤器的长度就得是n的4.2倍,我就不按照4.2倍来了,直接给5倍。

框架:
在这里插入图片描述

注意上面得用const static才能在类内这样写,不然会报错的。因为浮点数、类对象以及字符串是不允许作为非类型模板参数的,只能是整形,而且传参时必须传常量。非类型的模板参数必须在编译期就能确认结果。

然后和位图一样,先搞set接口。
在这里插入图片描述

就把映射出的各个位置置为1就行了,但是要注意字符串哈希最后得到的数字可能会很大而导致超过了布隆过滤器的长度,所以要用除留余数法来使得得到的数在正确范围内。

然后就是test:
在这里插入图片描述

注意只有false返回的才是绝对正确的,当返回true的时候,不一定正确,可能会误判。

下面就用如下代码测试一下:

BloomFilter<10> bf;
string arr1[] = { "苹果", "西瓜", "阿里", "美团", "苹果", "字节", "西瓜", "苹果", "香蕉", "苹果", "腾讯" };

for (auto& str : arr1)
{
	bf.Set(str);
}

for (auto& str : arr1)
{
	cout << bf.Test(str) << ' ';
}
cout << endl << endl;

string arr2[] = { "苹果111", "西瓜", "阿里2222", "美团", "苹果dadcaddxadx", "字节", "西瓜sSSSX", "苹果 ", "香蕉", "苹果$", "腾讯" };

for (auto& str : arr2)
{
	cout << str << ":" << bf.Test(str) << endl;
}

结果如下:
在这里插入图片描述

上方并没有出现误判的情况。

误判率测试

再来写一个测试误判率的程序:

void TestBloomFilter2()
{
	srand(time(0));
	const size_t N = 1000000;
	BloomFilter<N> bf;

	std::vector<std::string> v1;
	std::string url = "https://www.cnblogs.com/-clq/archive/2012/05/31/2528153.html";

	for (size_t i = 0; i < N; ++i)
	{
		v1.push_back(url + std::to_string(1234 + i));
	}

	for (auto& str : v1)
	{
		bf.Set(str);
	}

	// 相似
	std::vector<std::string> v2;
	for (size_t i = 0; i < N; ++i)
	{
		std::string url = "http://www.cnblogs.com/-clq/archive/2021/05/31/2528153.html";
		url += std::to_string(1234 + i);
		v2.push_back(url);
	}

	size_t n2 = 0;
	for (auto& str : v2)
	{
		if (bf.Test(str))
		{
			++n2;
		}
	}
	cout << "相似字符串误判率:" << (double)n2 / (double)N << endl;

	std::vector<std::string> v3;
	for (size_t i = 0; i < N; ++i)
	{
		string url = "zhihu.com";
		url += std::to_string(rand() + i);
		v3.push_back(url);
	}

	size_t n3 = 0;
	for (auto& str : v3)
	{
		if (bf.Test(str))
		{
			++n3;
		}
	}
	cout << "不相似字符串误判率:" << (double)n3 / (double)N << endl;
}

在布隆过滤器大小是插入数据的五倍的时候:

10万个数:
在这里插入图片描述

100万个数:
在这里插入图片描述

在布隆过滤器大小是插入数据的十倍的时候:

10万个数:
在这里插入图片描述
100万个数:
在这里插入图片描述
程序挂掉了。。
调试起来发现栈溢出了:
在这里插入图片描述
原因是STL库中实现的bitset是用静态数组实现的,所以刚执行程序光是数组就会在栈中开非常大的空间,所以就会导致栈溢出。

想要解决的话,就得在堆中开空间。两种方法。
一种是用我们自己实现的bitset:
在这里插入图片描述

另一种是还用库中的bitset,但是要改成指针,同时把类中用.调用的函数改为用->调用。
在这里插入图片描述

可以看到,布隆过滤器越长,误判率就越低,但是效率会变慢。

再来说一下布隆过滤器的reset。
直接说了,其实布隆过滤器不支持reset,因为一个字符串reset了可能会影响到其他字符串,想要解决这个问题的话,给每一个位置多给几个位,用来做引用计数,但是这样就会导致更多的空间消耗,从而就使得布隆过滤器的优势削弱了。所以说布隆过滤器一般是不支持删除的。这里也就不讲了。

几道题

  1. 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出
    精确算法和近似算法
  2. 如何扩展BloomFilter使得它支持删除元素的操作
  3. 给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?
  4. 与上题条件相同,如何找到top K的IP?

还是挨个来说:

  1. 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出
    精确算法和近似算法

这道题先说近似算法,就是布隆过滤器。query就是网络请求、sql语句什么的,本质上都是字符串。那么我们就可以先让一个文件中的query先翻到一个布隆过滤器中,然后让另一个文件中的query在布隆过滤器中查找。

再说精确算法。要用到哈希切分(先不说是什么意思)。
我们来假设两个条件。

  1. 假设每个query为30Byte,100亿个query就是3000亿个Byte,那么大概就是300个G。
  2. 假设两个文件名为A和B。

如果将两个文件均分为300个小文件的话,先将A中的一个小文件加载到布隆过滤器中,再从B中的每个小文件进行查找,由此可见,效率非常低下。

但是如果我们将每个字符串哈希后,再经过除留余数法(假如说%的是1000)后结果相同的字符串放到一个小文件中呢?
.
比如说A中的一大堆字符串经过哈希算法之后得到的结果是394,那么就将这些字符串全部放到A的第394号文件中。B中同理。把每一个小文件都表上各自的序号,Ai和Bi(i为从0到999的整数)。
.
经过哈希算法之后,A和B两个大文件就各自分出了1000个小文件,并且每个标号相同的AB小文件中字符串哈希后的结果都相同。
.
那么我们就能让标号相同的文件中的字符串进行对比,比如说A0和B0,两文件中字符串哈希后的结果都相同,那么相同的字符串就一定在标号相同的文件中。让对应标号的AB文件进行对比,这样查找效率一下子就上来了。

上面将对应哈希后的结果放到同一文件中,这就是哈希切分。

  1. 如何扩展BloomFilter使得它支持删除元素的操作

上面将布隆过滤器的最后已经说过了,这里就不多提了。

  1. 给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?

这里也是要用到哈希切分。IP地址也是可以用哈希算法来得到对应位置的。

只要把IP哈希后结果相同的放到同一个小文件中就行,这样就一定能让相同的IP地址存到一个小文件中,然后再在每个小文件中统计一下出现的次数最多的就行,将挨个文件中最多的进行对比,直到找到最后一个小文件为止。

  1. 与上题条件相同,如何找到top K的IP?

还是上面的方法,不过是要用一下小堆(至于为啥是小堆就不讲了,TOPK问题,这在我前面数据结构的博客中有)。

该讲的都讲了。

到此结束。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/79424.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023年即将推出的CSS特性对你影响大不大?

Google开发者大会每年都会提出有关于 Web UI 和 CSS 方面的新特性&#xff0c;今年又上新了许多新功能&#xff0c;今天就从中找出了影响最大的几个功能给大家介绍一下 :has :has() 可以通过检查父元素是否包含特定子元素或这些子元素是否处于特定状态来改变样式&#xff0c;也…

【JavaEE进阶】MyBatis的创建及使用

文章目录 一. MyBatis简介二. MyBatis 使用1. 数据库和数据表的创建2. 创建Mybatis项目2.1 添加MyBatis框架支持2.2 设置MyBatis配置信息 3. MyBatis开发流程4. MyBatis查询数据库测试 三. MyBatis 流程1. MyBatis 查询数据库流程2. MyBatis 框架交互流程图 一. MyBatis简介 M…

Springboot 实践(8)springboot集成Oauth2.0授权包,对接spring security接口

此文之前&#xff0c;项目已经添加了数据库DAO服务接口、资源访问目录、以及数据访问的html页面&#xff0c;同时项目集成了spring security&#xff0c;并替换了登录授权页面&#xff1b;但是&#xff0c;系统用户存储代码之中&#xff0c;而且只注册了admin和user两个用户。在…

Tomcat 部署优化

Tomcat Tomcat 开放源代码web应用服务器&#xff0c;是由java代码开发的 tomcat就是处理动态请求和基于java代码的页面开发 可以在html当中写入java代码&#xff0c;tomcat可以解析html页面当中的iava&#xff0c;执行动态请求 动态页面机制有问题&#xff1a;不对tomcat进行优…

仿牛客论坛项目day7|Kafka

一、阻塞队列 创建了一个生产者线程和一个消费者线程。生产者线程向队列中放入元素&#xff0c;消费者线程从队列中取出元素。我们可以看到&#xff0c;当队列为空时&#xff0c;消费者线程会被阻塞&#xff0c;直到生产者线程向队列中放入新的元素。 二、Kafka入门 发布、订阅…

mysql数据库迁移

目录 背景迁移数据库 背景 公司有个项目&#xff0c;刚开始数据量不是大的时候&#xff0c;数据库和服务上的所有应用数据都放在一个旧小盘中&#xff0c;随着项目数据的增长&#xff0c;旧的磁盘被占满了&#xff0c;导致系统无法写入数据&#xff0c;我和同事排查了很长时间…

阿里云云主机_ECS云服务器_轻量_GPU_虚拟主机详解

阿里云云主机分为云虚拟主机、云服务器ECS、轻量应用服务器、GPU云服务器、弹性裸金属服务器、专有宿主机、FPGA云服务器、高性能计算E-HPC、无影云电脑等&#xff0c;阿里云百科来详细说下阿里云云主机详解&#xff1a; 目录 阿里云云主机 云服务器ECS 轻量应用服务器 云…

C++ 面向对象三大特性——多态

✅<1>主页&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;C 继承 ☂️<3>开发环境&#xff1a;Visual Studio 2022 &#x1f4ac;<4>前言&#xff1a;面向对象三大特性的&#xff0c;封装&#xff0c;继承&#xff0c;多态&#xff…

红帽8.2版本CSA题库:第十一题查找文件

红帽8.2版本CSA题库&#xff1a;第十一题查找文件 touch /tmp/{gamelan,jacques,libWedgeit.so.1.2.3} chown jacques:jacques /tmp/{gamelan,jacques,libWedgeit.so.1.2.3}mkdir /root/findfiles #创建文件夹 find / -user jacques -exec cp -a {} /root/findfiles \; …

Centos7安装Docker及配置加速器地址

一、安装docker #1.yum 包更新到最新 yum update #2.安装需要的软件包&#xff0c;yum-util 提供yum-config-manager功能&#xff0c;另外两个是devicemapper驱动依赖的 yum install -y yum-utils device-mapper-persistent-data lvm2 #3.设置yum源 yum-config-manager --add…

Leetcode每日一题:1444. 切披萨的方案数(2023.8.17 C++)

目录 1444. 切披萨的方案数 题目描述&#xff1a; 实现代码与解析&#xff1a; 二维后缀和 动态规划 原理思路&#xff1a; 1444. 切披萨的方案数 题目描述&#xff1a; 给你一个 rows x cols 大小的矩形披萨和一个整数 k &#xff0c;矩形包含两种字符&#xff1a; A …

BC136 KiKi去重整数并排序

给定一个整数序列&#xff0c;KiKi想把其中的重复的整数去掉&#xff0c;并将去重后的序列从小到大排序输出。 输入描述 第一行&#xff0c;输入一个整数n&#xff0c;表示序列有n个整数。 第二行输入n个整数&#xff08;每个整数大于等于1&#xff0c;小于等于1000&#xf…

【日常积累】Linux之init系统学习

init系统简介: Linux 操作系统的启动首先从 BIOS 开始&#xff0c;接下来进入 boot loader&#xff0c;由 bootloader 载入内核&#xff0c;进行内核初始化。内核初始化的最后一步就是启动 pid 为 1 的 init 进程&#xff0c;这个进程是系统的第一个进程&#xff0c;它负责产生…

企望制造ERP系统 RCE漏洞复现

0x01 产品简介 企望制造纸箱业erp系统由深知纸箱行业特点和业务流程的多位IT专家打造&#xff0c;具有国际先进的管理方式&#xff0c;将现代化的管理方式融入erp软件中&#xff0c;让企业分分钟就拥有科学的管理经验。 erp的功能包括成本核算、报价定价、订单下达、生产下单、…

编程语言学习笔记-架构师和工程师的区别,PHP架构师之路

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责…

Unity游戏源码分享-中国象棋Unity5.6版本

Unity游戏源码分享-中国象棋Unity5.6版本 项目地址&#xff1a; https://download.csdn.net/download/Highning0007/88215699

TCP拥塞控制简单理解

1.TCP的控制机制 序号 TCP通过序号可以实现一下几个功能&#xff1a; 1.确认应答处理。发送端收到接收端的确认应答&#xff0c;可以得知某些数据包被接收端接收了 2.顺序控制。接收端可以利用序号对接收到的报文进行排序 3.重发控制。如果发送端没有收到确认应答&#xff0c…

vue项目引入antDesignUI组件

快速安装ant-design-vue并配置&#xff0c;vue2.0 antDesign1.7.8 第一步&#xff1a;安装ant-deisgn-vue 1.7.8 npm install ant-design-vue1.7.8 --save第二步&#xff1a;配置package.json文件&#xff0c;将依赖写入后&#xff0c;npm install 安装依赖 "dependenc…

智慧建筑工地平台,通过信息化技术、物联网、人工智能技术,实现对施工全过程的实时监控、数据分析、智能管理和优化调控

智慧工地是指通过信息化技术、物联网、人工智能技术等手段&#xff0c;对建筑工地进行数字化、智能化、网络化升级&#xff0c;实现对施工全过程的实时监控、数据分析、智能管理和优化调控。智慧工地的建设可以提高工地的安全性、效率性和质量&#xff0c;降低施工成本&#xf…

Maven官网下载配置新仓库

1.Maven的下载 Maven的官网地址&#xff1a;Maven – Download Apache Maven 点击Download&#xff0c;查找 Files下的版本并下载如下图&#xff1a; 2.Maven的配置 自己在D盘或者E盘创建一个文件夹&#xff0c;作为本地仓库&#xff0c;存放项目依赖。 将下载好的zip文件进行解…