bingc++(mapset树哈希位图布隆过滤器)

Posted 月屯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bingc++(mapset树哈希位图布隆过滤器)相关的知识,希望对你有一定的参考价值。

上一篇

目录标题

前言

底层为红黑树结构C++98二叉搜索树+平衡限制

  • map: K-V–键值对—key必须唯一
  • set: K—key必须唯一
  • multimap: K-V–键伯对—key是可以重复
  • multiset K----key是可以重复

底层为哈希结构:C++11
都足关于key有序的,并且查找的时间复杂度都是O(IogN)

map

基本使用

map[]运算符重载做法

map中的顺序

默认按key升序,如果key一致,按照升序

multimap

基本使用

#include <iostream>
using namespace std;

#include <map>
#include <string>
int main()

	multimap<string, string> m;
	m.insert(pair<string, string>("orange", "橙子"));
	m.insert(make_pair("pear", "梨"));
	m.insert(make_pair("banana", "香蕉"));
	m.insert(make_pair("apple", "苹果"));
	m.insert(make_pair("orange", "橘子"));

	cout << m.size() << endl;
	cout << m.count("orange") << endl;

	m.erase("orange");
	if (m.find("orange") != m.end())
	
		cout << "删除了一个" << endl;
	
	else
	
		cout << "删除所有key为orange的键值对" << endl;
	

	for (auto& e : m)
	
		cout << e.first << "--->" << e.second << endl;
	
	cout << endl;

	return 0;

set

二叉搜索树

平衡二叉树

红黑树

  • 红黑树的性质
    1.每个结点不是红色就是黑色
    2.根节点是黑色
    3如果一个节点是红色的,则它的两个孩子结点是黑色的每条路径中黑色节点个数相同(不会出现连在一起的红色节点)
    4.对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
    5.每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

    约定:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点

  • 情况一: cur为红,p为红,g为黑,u存在且为红
    解决:p、u调黑,g调红
    1.如果g是根节点,调整完成后,需要将g改为黑色
    2.如果g是子树,g一定有双亲,且g的双亲如果是红色,把g当成cur,需要继续向上调整,否则结束

  • 情况二: cur为红(p左孩子),p为红,g为黑,1.u不存在(cur新插入)/2.u为黑(cur不是新插入)

u是黑色时,为什么现在cur是红色的?
因为:新节点一定是插入到cur的子树中,导致子树违反了红黑树形式在调整的过程当中,将cur由黑色改成了红色才出现现在所看到的场景

cur和p其中一个节点的颜色一定要设置成黑色注意: cur肯定不能设置为黑色
因为:如果叔叔节点存在并且为黑色时,cur之前的颜色一定是黑色的,往上调整的时候好不容易将cur由黑色改成红色,cur及其子树满足红黑树的性质,现在如果将cur直接改成黑色,则会导致cur子树不满足红黑树的性质
想法:只能将p设置为黑色

解决方案
将双亲和祖父节点的颜色交换对g子树进行右单旋处理
p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,
p为g的右孩子,cur为p的右孩子,则进行左单旋转
p、g变色–p变黑,g变红

  • 情况三: cur为红(p右孩子),p为红,g为黑,u不存在/u为黑
    解决方案:变成情况二

    p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,
    p为g的右孩子,cur为p的左孩子,则针对p做右单旋转

map、set应用

哈希

哈希冲突

简单分析哈希函数设计是否合理

注意:
a.哈希函数的值域必须在表格的范围之内
b.哈希函数计算出的结果尽可能均匀
c.哈希函数设计尽可能简单

  • 直接定制法–(常用)
    取关键字的某个线性函数为散列地址:Hash(Key)= A*Key + B 优点:简单、均匀 缺点:需要事先
    知道关键字的分布情况 使用场景:适合查找比较小且连续的情况
    字符
  • 除留余数法–(常用)
    设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数,按照哈希函数:Hash(key) = key% p(p<=m),将关键码转换成哈希地址
  • 平方取中法–(了解)
    假设关键字为1234,对它平方就是1522756,抽取中间的3位227作为哈希地址; 再比如关键字为4321,对它平方就是18671041,抽取中间的3位671(或710)作为哈希地址 平方取中法比较适合:不知道关键字的分布,而位数又不是很大的情况
  • 折叠法–(了解)
    折叠法是将关键字从左到右分割成位数相等的几部分(最后一部分位数可以短些),然后将这几部分叠加求和,并按散列表表长,取后几位作为散列地址。折叠法适合事先不需要知道关键字的分布,适合关键字位数比较多的情况
  • 随机数法–(了解)
    选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H(key) = random(key),其中random为随机数函数。通常应用于关键字长度不等时采用此法
  • 数学分析法–(了解)
    设有n个d位数,每一位可能有r种不同的符号,这r种不同的符号在各位上出现的频率不一定相同,可能在某些位上分布比较均匀,每种符号出现的机会均等,在某些位上分布不均匀只有某几种符号经常出现。可根据散列表的大小,选择其中各种符号分布均匀的若干位作为散列地址。例如:
    假设要存储某家公司员工登记表,如果用手机号作为关键字,那么极有可能前7位都是 相同的,那么我们可以选择后面的四位作为散列地址,如果这样的抽取工作还容易出现 冲突,还可以对抽取出来的数字进行反转(如1234改成4321)、右环位移(如1234改成4123)、左环移位、前两数与后两数叠加(如1234改 成12+34=46)等方法。
    数字分析法通常适合处理关键字位数比较大的情况,如果事先知道关键字的分布且关键字的若干位分布较均匀的情况

注意:哈希函数设计的越精妙,产生哈希冲突的可能性就越低,但是无法避免哈希冲突

闭散列

线性探测


线性探测优点:解决冲突的方式简单
线性探测缺陷:容易产生数据的堆积(一旦产生冲突,冲突的元素容易连城一片)
合布负载因子:有效元素个数/表格容量

二次探测


闭散列源码

开散列


开散列源码

开散列的应用-- unordermap、unorderset


unorderset模拟
unordermap模拟

位图

#include <iostream>
using namespace std;
#include <bitset>

int main()

    int array[] =  1, 3, 7, 4, 12, 16, 19, 13, 22, 18 ;

    // 先要预算总共需要多少个比特位
    bitset<23> bs;

    // 将数组中的元素映射到位图中
    for (auto e : array)
        bs.set(e);

    cout << bs.count() << endl;
    cout << bs.size() << endl;

    if (bs.test(13))
        cout << "13 is in array" << endl;
    else
        cout << "13 is not in array" << endl;

    bs.reset(13);
    if (bs.test(13))
        cout << "13 is in array" << endl;
    else
        cout << "13 is not in array" << endl;

    cout << bs.to_string() << endl;
    cout << bs.to_ulong() << endl;


    bitset<32>  bs1(0x55555555);
    cout << bs1.to_string() << endl;
    return 0;

模拟源码

位图的应用

  1. 快速查找某个数据是否在一个集合中
  2. 排序
  3. 求两个集合的交集、并集等
  4. 操作系统中磁盘块标记

布隆过滤器

布隆过滤器是由布隆(Burton Howard Bloom)在1970年提出的 一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间。

源码模拟
布隆过滤器优点

  1. 增加和查询元素的时间复杂度为:O(K), (K为哈希函数的个数,一般比较小),与数据量大小无关
  2. 哈希函数相互之间没有关系,方便硬件并行运算
  3. 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势
  4. 在能够承受一定的误判时,布隆过滤器比其他数据结构有这很大的空间优势
  5. 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能
  6. 使用同一组散列函数的布隆过滤器可以进行交、并、差运算
    布隆过滤器缺陷
  • 有误判率,即存在假阳性(False Position),即不能准确判断元素是否在集合中(补救方法:再建立一个白
    名单,存储可能会误判的数据)
  • 不能获取元素本身
  • 一般情况下不能从布隆过滤器中删除元素
  • 如果采用计数方式删除,可能会存在计数回绕问题

常见面试题







哈希加密
一致性哈希

以上是关于bingc++(mapset树哈希位图布隆过滤器)的主要内容,如果未能解决你的问题,请参考以下文章

bingc++(mapset树哈希位图布隆过滤器)

哈希结构(图文详解)哈希表,哈希桶,位图,布隆过滤器

哈希应用及海量数据面试题

哈希应用及海量数据面试题

C++从青铜到王者第二十一篇:哈希的应用之位图布隆过滤器

哈希表应用(位图和布隆过滤器)