搞懂位图和布隆过滤器

news2024/9/23 22:33:21

文章目录

    • 位图
      • 腾讯面试题
      • 位图概念
      • 位图实现
      • 位图的应用
      • 位图的应用题
    • 布隆过滤器
      • 布隆过滤器提出
      • 布隆过滤器概念
      • 布隆过滤器实现原理
      • 布隆过滤器的应用场景
      • 如何选择哈希函数个数和布隆过滤器长度 - - 目的减少误判率
      • 布隆过滤器的实现
      • 布隆过滤器优点
      • 布隆过滤器缺陷
    • 海量数据面试题
      • 哈希切割
      • 布隆过滤器
    • 一致性哈希,服务器设计(了解)

位图

腾讯面试题

题目:
给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。

解决方法:

1.遍历,时间复杂度O(N)。
2.外排序(O(NlogN)),利用二分查找磁盘: logN,访问磁盘次数很多,效率很低。liunx排序指令
3.位图解决。- - 针对整形的 直接定址法。

数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。比如

在这里插入图片描述

位图概念

所谓位图,就是用每一位来存放某种状态,通常是用来判断某个数据存不存在的。适用于海量数据,数据无重复的场景。

位图实现

  • 不需要考虑大小端。
  • 非类型模板参数 N 表示N个元素
	template<size_t N>
	class bitset
	{
	public:
		bitset()
		{
			_bits.resize(N/8+1, 0);// 开辟空间以字节为单位
		}
		// 设置对应位 为 1
		void set(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;

			_bits[i] |= (1 << j);
		}
		// 设置对应位位 0
		void reset(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;

			_bits[i] &= ~(1 << j);
		}
		// 测试 x 对应位是否为 1
		bool test(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;


			return _bits[i] & (1 << j);
		}

	private:
		vector<char> _bits;
	};

	void test_bit_set1()
	{
		bitset<100> bs1;
		bs1.set(8);
		bs1.set(9);
		bs1.set(20);

		cout << bs1.test(8) << endl;
		cout << bs1.test(9) << endl;
		cout << bs1.test(20) << endl;

		bs1.reset(8);
		bs1.reset(9);
		bs1.reset(20);

		cout << bs1.test(8) << endl;
		cout << bs1.test(9) << endl;
		cout << bs1.test(20) << endl;
	}

// 开辟。
	void test_bit_set2()
	{
	// 可以记录所有int整数状态
		bitset<-1> bs1;// 开辟512MB
		//bitset<0xffffffff> bs2;
	}


位图的应用

  1. 快速查找某个数据是否在一个集合中。
  2. 给正整数排序 + 去重 - - 时间 O(N) ,N:正整数的最大值,N越大位图越大 ,由于语言数据类型的限制,所以 N最大是 MAX_UNSIGNED_LONG_LONG 。当然也可以进行大数运算,大数运算有很多种,模拟法,位运算法,
  3. (了解)虽然c语言只支持int,long类型来存放数据, 实际计算机是使用位运算计算的,底层就是存放二进制数01序列,语言层限制了数据的范围,如果我们要进行大数运算,可以使用位运算进行模拟,例如,0xFFFFFFFFFFFFFFFF1数据已经突破了 unsigned long long 类型了,我们可以转换位 位图进行存储,让后使用位运算 计算. 转换过程比较复杂所以了解性学习
  4. 求两个集合的交集、并集等
  5. 操作系统中磁盘块标记
  6. 速度快,空间小。
  7. 局限性,只能映射处理整形。如果元素要进行哈希计算,那么映射的位置存在冲突,而位图不能处理冲突的。所以位图采用的是直接定址法,不会产生冲突。

位图的应用题

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

解题步骤:

  • 100亿个整数会出现重复,整数的范围在 0~4294967295,因此实际只需要开辟 4294967295个比特位就行。即 0xFFFFFFFF。
  • 两张位图加起来为 85亿多比特位。
  • 使用两个位图表表示 0,1和1次以上的状态。
	template<size_t N>
	class twobitset
	{
	public:
		void set(size_t x)
		{
			bool inset1 = _bs1.test(x);
			bool inset2 = _bs2.test(x);

			// 00
			if (inset1 == false && inset2 == false)
			{
				// -> 01
				_bs2.set(x);
			}
			else if (inset1 == false && inset2 == true)
			{
				// ->10
				_bs1.set(x);
				_bs2.reset(x);
			}
			else if (inset1 == true && inset2 == false)
			{
				// ->11
				_bs1.set(x);
				_bs2.set(x);
			}
		}
	
		// 遍历所有正整数,打印条件满足只出现一次的整数
		void print_once_num()
		{
			for (size_t i = 0; i < N; ++i)
			{
				if (_bs1.test(i) == false && _bs2.test(i) == true)
				{
					cout << i << endl;
				}
			}
		}

	private:
		bitset<N> _bs1;
		bitset<N> _bs2;
	};

	void test_bit_set3()
	{
		int a[] = { 3, 4, 5, 2, 3, 4, 4, 4, 4, 12, 77, 65, 44, 4, 44, 99, 33, 33, 33, 6, 5, 34, 12 };

		twobitset<100> bs;
		for (auto e : a)
		{
			bs.set(e);
		}

		bs.print_once_num();
	}

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

解决步骤:

  • 100亿个整数会出现重复,整数的范围在 0~4294967295,因此实际只需要开辟 4294967295个比特位就行。即 0xFFFFFFFF。
  • 两张位图加起来为 85亿多比特位。
  • 使用两个位图,对应都是1就是交集。
	template<size_t N>
	class twobitset
	{
	public:
		void set(vector<int>& a, vector<int>& b)
		{
			for (auto e : a)
			{
				_bs1.set(e);
			}
			for (auto e : b)
			{
				_bs2.set(e);
			}
		}

		void print_union_num()
		{
			for (size_t i = 0; i < N; ++i)
			{
				if (_bs1.test(i) == true && _bs2.test(i) == true)
				{
					cout << i << endl;
				}
			}
		}

	private:
		bitset<N> _bs1;
		bitset<N> _bs2;
	};

	void test_bit_set4()
	{
		vector<int> a = { 3, 4, 5, 2, 3, 4, 4, 4, 4, 12, 77, 65, 44, 4, 44, 99, 33, 33, 33, 6, 5, 34, 12 };
		vector<int> b = { 3,4,5,12,23};

		twobitset<100> bs;
		bs.set(a, b);
		bs.print_union_num();
	}

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

解题步骤:

  • 类似,用两个位图记录4种转态,00:0次,01:1次,10:2次,11:三次即以上
template<size_t N>
class twobitset
{
public:

	void set(size_t x)
	{
		bool inset1 = _bs1.test(x);
		bool inset2 = _bs2.test(x);

		// 00
		if (inset1 == false && inset2 == false)
		{
			// -> 01
			_bs2.set(x);
		}
		else if (inset1 == false && inset2 == true)
		{
			// ->10
			_bs1.set(x);
			_bs2.reset(x);
		}
		else if (inset1 == true && inset2 == false)
		{
			// ->11
			//_bs1.set(x);
			_bs2.set(x);
		}
	}

	// 
	void print_num(vector<int>& a)
	{
		for (size_t i = 0; i < a.size(); ++i)
		{
			// 10
			if (_bs1.test(a[i]) == true && _bs2.test(a[i]) == false)
			{
				cout << a[i] << endl;
			}
			// 01
			else if (_bs1.test(a[i]) == false && _bs2.test(a[i]) == true)
			{
				cout << a[i] << endl;
			}
			// 00
			else if (_bs1.test(a[i]) == false && _bs2.test(a[i]) == false)
			{
				cout << a[i] << endl;
			}

		}
	}

private:
	bitset<N> _bs1;
	bitset<N> _bs2;
};

void test_bit_set5()
{
	vector<int> a = { 3,5, 2, 3, 4, 4, 4, 4, 12,12 , 77, 65, 44,44,  33, 33, 33, 34};
	//int a[] = { 3,3,3,3 };

	twobitset<100> bs;
	for (auto e : a)
	{
		bs.set(e);
	}

	bs.print_num(a);
}

}

布隆过滤器

布隆过滤器提出

我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉
那些已经看过的内容。问题来了,新闻客户端推荐系统如何实现推送去重的? 用服务器记录了用
户看过的所有历史记录,当推荐系统推荐新闻时会从每个用户的历史记录里进行筛选,过滤掉那
些已经存在的记录。 如何快速查找呢?

  1. 用哈希表存储用户记录,缺点:浪费空间
  2. 用位图存储用户记录,缺点:位图一般只能处理整形,如果内容编号是字符串,就无法处理
    了。
  3. 将哈希与位图结合,即布隆过滤器。

布隆过滤器概念

布隆过滤器是由布隆(Burton Howard Bloom)在1970年提出的 一种紧凑型的、比较巧妙的概
率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存
在”
,它是用多个哈希函数,将一个数据映射到位图结构中。相比于传统的 List、Set、Map 等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的。

https://zhuanlan.zhihu.com/p/43263751/

布隆过滤器实现原理

1.HashMap 的问题

讲述布隆过滤器的原理之前,我们先思考一下,通常你判断某个元素是否存在用的是什么?应该蛮多人回答 HashMap 吧,确实可以将值映射到 HashMap 的 Key,然后可以在 O(1) 的时间复杂度内返回结果,效率奇高。但是 HashMap 的实现也有缺点,例如存储容量占比高,考虑到负载因子的存在,通常空间是不能被用满的,而一旦你的值很多例如上亿的时候,那 HashMap 占据的内存大小就变得很可观了。

还比如说你的数据集存储在远程服务器上,本地服务接受输入,而数据集非常大不可能一次性读进内存构建 HashMap 的时候,也会存在问题。

2.布隆过滤器数据结构

布隆过滤器是一个 bit 向量或者说 bit 数组,长这样:

在这里插入图片描述

如果我们要映射一个值到布隆过滤器中,我们需要使用多个不同的哈希函数生成多个哈希值,并对每个生成的哈希值指向的 bit 位置 1,例如针对值 “baidu” 和三个不同的哈希函数分别生成了哈希值 1、4、7,则上图转变为:

在这里插入图片描述Ok,我们现在再存一个值 “tencent”,如果哈希函数返回 3、4、8 的话,图继续变为:

在这里插入图片描述
值得注意的是,4 这个 bit 位由于两个值的哈希函数都返回了这个 bit 位,因此它被覆盖了。现在我们如果想查询 “dianping” 这个值是否存在,哈希函数返回了 1、5、8三个值,结果我们发现 5 这个 bit 位上的值为 0,说明没有任何一个值映射到这个 bit 位上,因此我们可以很确定地说 “dianping” 这个值不存在。

而当我们需要查询 “baidu” 这个值是否存在的话,那么哈希函数必然会返回 1、4、7,然后我们检查发现这三个 bit 位上的值均为 1,那么我们可以说 “baidu” 存在了么?答案是不确定,只能说 “baidu” 这个值可能存在。

这是为什么呢?答案跟简单,因为随着增加的值越来越多,被置为 1 的 bit 位也会越来越多,这样某个值 “taobao” 即使没有被存储过,但是万一哈希函数返回的三个 bit 位都被其他值置位了 1 ,那么程序还是会判断 “taobao” 这个值存在。

结论:

在:不准确,存在误判。
不在:准确,不存在误判。

3. 支持删除么

传统的布隆过滤器并不支持删除操作。但是名为 Counting Bloom filter 的变种可以用来测试元素计数个数是否绝对小于某个阈值,它支持元素删除。可以参考文章 Counting Bloom Filter 的原理和实现

布隆过滤器的应用场景

布隆过滤器能够快速的确认一个元素是否存在,但是存在误判。一些场景下可以允许出现误判,还有一些不允许出现误判。我们对这两种场景分别举例说明。
1.黑名单场景

场景:我们要记录用户信息,有一份黑名单,如果用户在黑名单里,那么就不记录该用户的信息。黑名单数量很大存放在数据库里,但是数据库访问很慢,如果用set记录,内存不够。

解决方法:

在内存里创建布隆过滤器,如果在那么再到数据库确认,因为“在” 存在误判 ,如果不在,直接返回。

优势:

set,map 空间大,可能存放不下黑名单。
布隆过滤器能减少访问数据库的次数,提高效率。
在这里插入图片描述
2.昵称是否被占用场景

场景:注册页面,快速输入提示昵称死否被占用。

在这种场景下是允许存在误判的。
在这里插入图片描述

如何选择哈希函数个数和布隆过滤器长度 - - 目的减少误判率

什么是误判? 实际不存在的元素,被判断为存在。判断的结果是错误的。

很显然,过小的布隆过滤器很快所有的 bit 位均为 1,那么查询任何值都会返回“可能存在”,起不到过滤的目的了。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。

另外,哈希函数的个数也需要权衡,个数越多则布隆过滤器 bit 位置位 1 的速度越快,且布隆过滤器的效率越低;但是如果太少的话,那我们的误报率会变高。

如下图:k 为哈希函数个数,m 为布隆过滤器长度,n 为插入的元素个数,p 为误报率。
在这里插入图片描述

如何选择适合业务的 k 和 m 值呢,这里直接贴一个公式:

在这里插入图片描述

例如:
假设k为3,即hash函数的个数为3,

k=m/n * 0.7
4.2n=m

即hash函数的个数为3时,布隆过滤器要开辟 4.2n个。

布隆过滤器的实现

1.哈希函数

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;
	}
};

2.布隆过滤器

注意:
STL 里 bitset存放在栈里,因此可能会导致栈溢出,我们把bitset对象转移到堆上就行。

// N表示准备要映射N个值
template<size_t N,
	class K = string, class Hash1 = HashBKDR, class Hash2 = HashAP, class Hash3 = HashDJB>
class BloomFilter
{
public:
	void Set(const K& key)
	{
		size_t hash1 = Hash1()(key) % (_ratio * N);
		//cout << hash1 << endl;

		_bits->set(hash1);

		size_t hash2 = Hash2()(key) % (_ratio * N);
		//cout << hash2 << endl;

		_bits->set(hash2);

		size_t hash3 = Hash3()(key) % (_ratio * N);
		//cout << hash3 << endl;

		_bits->set(hash3);
	}

	bool Test(const K& key)
	{
		size_t hash1 = Hash1()(key) % (_ratio * N);
		//cout << hash1 << endl;
		if (!_bits->test(hash1))
			return false; // 准确的

		size_t hash2 = Hash2()(key) % (_ratio * N);
		//cout << hash2 << endl;

		if (!_bits->test(hash2))
			return false; // 准确的

		size_t hash3 = Hash3()(key) % (_ratio * N);
		//cout << hash3 << endl;

		if (!_bits->test(hash3))
			return false;  // 准确的

		return true; // 可能存在误判
	}

	// 能否支持删除-> 
	void Reset(const K& key);

private:
	const static size_t _ratio = 5;
	// STL 里 bitset存放在栈里,因此可能会导致栈溢出,我们把bitset对象转移到堆上就行
	std::bitset<_ratio* N>* _bits = new std::bitset<_ratio* N>;
};

3.测试

测试 1

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

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

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

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

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

测试2:测试误判率

void TestBloomFilter2()
{
	srand(time(0));
	const size_t N = 100000;
	BloomFilter<N> bf;
	cout << sizeof(bf) << endl;

	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(rand() + 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;
}

4.布隆过滤器的删除

布隆过滤器不能直接支持删除工作,因为在删除一个元素时,可能会影响其他元素。

比如:删除上图中"tencent"元素,如果直接将该元素所对应的二进制比特位置0,“baidu”元素也
被删除了,因为这两个元素在多个哈希函数计算出的比特位上刚好有重叠。

一种支持删除的方法:将布隆过滤器中的每个比特位扩展成一个小的计数器,插入元素时给k个计
数器(k个哈希函数计算出的哈希地址)加一,删除元素时,给k个计数器减一,通过多占用几倍存储
空间的代价来增加删除操作。
缺陷:

  1. 无法确认元素是否真正在布隆过滤器中
  2. 存在计数回绕
  3. 优势被削弱

布隆过滤器优点

  1. 增加和查询元素的时间复杂度为:O(K), (K为哈希函数的个数,一般比较小),与数据量大小无
  2. 哈希函数相互之间没有关系,方便硬件并行运算
  3. 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势
  4. 在能够承受一定的误判时,布隆过滤器比其他数据结构有这很大的空间优势
  5. 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能
  6. 使用同一组散列函数的布隆过滤器可以进行交、并、差运算

布隆过滤器缺陷

  1. 有误判率,即存在假阳性(False Position),即不能准确判断元素是否在集合中(补救方法:再
    建立一个白名单,存储可能会误判的数据)
  2. 不能获取元素本身
  3. 一般情况下不能从布隆过滤器中删除元素
  4. 如果采用计数方式删除,可能会存在计数回绕问题

海量数据面试题

哈希切割

哈希切割将海量的数据通过哈希函数进行数据划分,相同哈希值的数据被归并到相同位置上。

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

  • map来记录,空间消耗大,内存存放不下。
  • 哈希切割法:
    • 如下图,每次读取一个ip,将ip进行哈希取模求出i,然后将这个ip进入第i个小文件里。
    • 每个小文件存在不同种类的ip,但是相同的ip,一定进入同一个小文件里。
    • 此时,小文件可以加载到内存里,我们可以使用map<string,in> 统计每个小文件IP次数。每次统计完一个小文件就能求出此时小文件的最大次数的IP,释放map<string,int>。
    • 注意:小文件可能进入的ip数量比较多,小文件可能太大无法加载到内存,我们只需要再次将小文件进行哈希切割即可,当然此时哈希函数要改变一下。

在这里插入图片描述

2.与上题条件相同,如何找到top K的IP?如何直接用Linux系统命令实现?

解题步骤:

  • 建立一个K个<string,int>的小堆。
  • 与上题相同,先哈希切割,然后统计每个小文件,最好插入到小堆里。

3. 有3台集群服务器,如何通过id将数据存放到这个三台服务器上

解题步骤:

  • 如下图,给服务器进行编号,通过id求出哈希值。
  • 注意:如果服务器增多了怎么办?- 一致性哈希 ,服务器设计

在这里插入图片描述

布隆过滤器

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

解题步骤:

  • 近似算法:
    • 提供一个布隆过滤器解决。
  • 精确算法:
    • 如下图,A和B两个文件,
    • 依次读取A文件中query,i = hash(query) % 1000 ,将这个query存进Ai小文件里。
    • B文件也如此操作。
    • 每次 ,编号相同的Ai 和 Bi 放到内存的set中找交集。

在这里插入图片描述

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

一致性哈希,服务器设计(了解)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

科普帖:如何提升Watch Buds的音质体验,看这里!

对于追求小巧便携的友友们来说&#xff0c;华为Watch Buds耳机可谓是非常惊喜的存在。华为Watch Buds耳机形态独树一帜&#xff0c;同时在耳机控制上做了一个广域耳廓触控功能&#xff0c;是华为首次采用的功能。即耳机、耳廓或靠近耳屏的脸颊区域都可操控&#xff0c;双击可接…

【MYSQL】Java的JDBC编程(idea连接数据库)

1. 配置 &#xff08;1&#xff09;新建一个项目 &#xff08;2&#xff09;Build System 那里选择Maven,下一步Create &#xff08;3&#xff09;配置pom.xml文件 首先查看自己的MYSQL版本&#xff1a;进入MySQL命令窗口 我的MYSQL版本是8.0版本的. 下一步&#xff0c;…

【Java基础】Java总览

一、what-什么是Java&#xff1f; Java是一种面向对象的编程语言&#xff0c;其他面向对象的编程语言还有C#&#xff0c;C&#xff0c;Python&#xff0c;Python&#xff0c;golang&#xff0c;VB等。 1、和其他语音对比 对比项\语言CCJava上线时间1972年1979年1995年特点面向…

[pgrx开发postgresql数据库扩展]3.hello world全流程解析

数据库的扩展开发框架 一般来说&#xff0c;数据库的扩展开发主要有的目的就是扩展数据库引擎的能力&#xff08;不管是用pgrx还是其他的框架都一样&#xff09;&#xff1a; 例如PostgreSQL上最著名的扩展PostGIS&#xff0c;就是扩展了PG数据库的空间数据支持能力&#xff…

Linearx配置环境

代码地址 gitssh.dev.azure.com:v3/linearx/PowerDDS/PowerDDS LinearX-5G Wifi pwd: 50186058 Windows报错可以搜索错误代码找官方给出的解决方案 最新版本cmake&#xff1a;ubuntu 20.04安装(升级)cmake - 知乎 (zhihu.com) gtest&#xff1a;gtest的安装_liuzubing的博客…

图论 Kruskal 最小生成树算法

前置知识 关于最小生成树 先说「树」和「图」的根本区别&#xff1a;树不会包含环&#xff0c;图可以包含环 树就是「无环连通图」 生成树是含有图中所有顶点的「无环连通子图」 你要保证这些边&#xff1a; 1、包含图中的所有节点。 2、形成的结构是树结构&#xff08;即不…

NFS共享存储服务

目录 一、NFS简介二. NFS工作原理实验&#xff1a;准备一台服务器&#xff0c;一台客户端。实现共享目录服务器上发布共享目录配置操作客户端配置操作 总结 一、NFS简介 NFS&#xff08;Network File System 网络文件服务&#xff09; NFS 是一种基于 TCP/IP 传输的网络文件系…

五一国际劳动节知多少!祝五一劳动节快乐! Happy International Workers‘Day!

五一国际劳动节简称五一节&#xff0c;在每年的5月1日&#xff0c;它是全世界劳动人民的共同节日。5.1 International labor Days call 5.1 sections, May 1 in every year. It is the whole world labor common festival of the people. 劳动是人类的幸福之源。 Work is the t…

JQuery-原理示意图-- 选择器-- 选择器综合代码--jQuery 的 DOM 操作--增删改查节点--常用遍历节点方法--多选框应用--全部综合代码

目录 JQuery 基本介绍 jQuery 的原理示意图 JQuery 基本开发步骤 说明: jQuery简单示例 jQuery 对象和 DOM 对象 什么是 jQuery 对象 DOM 对象转成 jQuery 对象 应用实例 jQuery 对象转成 DOM 对象 代码演示 jQuery 选择器 jQuery 选择器介绍 jQuery 选择器的优…

Adaptive AUTOSAR 文档官方如何阅读

目前很多关于 Adaptive AUTOSAR 的文章都是官方文档的简化翻译&#xff0c;不如直接看官方文档更全面深入。 Adaptive AUTOSAR 文档官方下载地址 Adaptive Platform AUTOSARhttps://www.autosar.org/standards/adaptive-platform About The AUTOSAR Adaptive Platform impl…

JavaScript 教程---菜鸟教程

文章目录 JavaScript 教程JavaScript 输出JavaScript 对象JavaScript 函数JavaScript 事件 JS 函数JS 类JS HTML DOMJS 高级教程JS 浏览器 BOMJS 库 JavaScript 教程 JavaScript 输出 JavaScript 可以通过不同的方式来输出数据 使用window.alert()弹出警告框。 <script&…

物联网产品的开发的难点,致命点是什么?

物联网产品的开发的难点&#xff0c;致命点是什么&#xff1f; 当下是万物互联的时代&#xff0c; 物联网产品本身的难度因行业而异。但是物联网设备上云通信交互就成了各个行业需要首先解决的问题。 物联网通信问题从产品设计一开始&#xff0c;如果不能很好的解决&#xff0c…

C++引用详解

1.引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 比如&#xff1a; 这是简单的引用 注意&#xff1a;引用类型必须和引用实体是同一种类型。 2.…

数据仓库技术与Hive入门

文章目录 数据仓库基本概念场景案例主要特征主流开发语言-SQL数仓开发语言概述SQL语言介绍结构化数据SQL语法分类 Apache Hive入门Apache Hive 安装部署元数据 Hive SQL语言 数据仓库 基本概念 数据仓库(Data Warehouse,简称数仓、DW)&#xff0c;是一个用于存储&#xff0c;分…

FMC128:具有出色的同步性能-8通道同步采集

板卡概述 FMC128 是一款 8 通道 250MHz 采样率 16 位 AD 采集 FMC子卡&#xff0c;符合 VITA57 规范&#xff0c;可以作为一个理想的 IO 模块耦合至 FPGA 前端&#xff0c;8 通道 AD 通过高带宽的 FMC 连接器&#xff08;HPC&#xff09;连接至 FPGA 从 而大大降低了系统信号…

八、vue_options之computed、watch属性选项

一、computed计算属性使用 &#xff08;1&#xff09;复杂data的处理方式 &#xff08;2&#xff09;computed 计算属性 computed计算属性初体验&#xff1a; 在我们通过Vue调用createApp方法传入一个对象的时候&#xff0c;我们之前写了data属性、methods属性&#xff0c;这…

关于一个C++项目的总结与反思:bosot搜索引擎

文章目录 写在前面关于这个项目的收获简单的项目介绍整体逻辑与第三方库每一步的具体细节util.hppparser.ccindex.hppsearcher.hpphttp_server.hpp其他模块 项目地址&#xff1a;boost_searcher: 项目&#xff1a;boost站内搜索 (gitee.com) 写在前面 这个项目是用C写的&…

聚焦能源 | 赛宁网安亮相2023年中国能源网络安全大会

​​4月21日&#xff0c;2023年中国能源网络安全大会&#xff08;以下简称“大会”&#xff09;在江苏南京成功落幕&#xff01;为贯彻国家网络强国战略&#xff0c;加强能源网络安全技术创新、成果应用、人才培养与技术交流&#xff0c;大会推出主旨论坛、案例交流、展览展示等…

python:根据灰度值检查成像是否存在黑图情况

一、需求描述 1、摄像机在拍照的时候&#xff0c;会打开闪光灯进行拍照&#xff0c;假如闪光灯在拍照之后打开&#xff0c;就会产生黑图 2、因此&#xff0c;我们需要摄像机采集很多图片&#xff0c;检查是否每次拍照都是正常的 3、我们可以通过人眼进行查看&#xff0c;但是…

SpringCloud入门实战(七)-Hystrix服务熔断入门案例

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术&#xff0c;都可以先去官网先看看&…