MSVC的unordered_set的插入会先计算value的对应hash值_Bucket,通过_Bucket可以找到vect指向的元素链表指针low和high(vect的大小是槽数量的两倍,_Vec[_2 * _Bucket]指向low,_Vec[_2 * _Bucket + 1]指向high)。通过low和high的状态,unordered_set可以确定_Bucket对应的槽是否已有元素插入。 如果_Bucket对应槽已有元...
没问题 然后,unordered_map的插入 没问题。 4. 哈希表迭代器的实现 接着我们来实现一下哈希表的迭代器 我们来思考一下它的迭代器应该怎么搞: 那按照我们以往的经验,它的迭代器应该还是对结点指针的封装,然后顺着每个不为空的哈希桶(链表)进行遍历就行了。 那大家思考一下: 比如现在底层的哈希表是这样的,it在...
红黑树实现map、set的封装 ,而 unordered_set 和 unordered_map 的功能与map和set类似,所不同的是其存储元素是无序的,底层是使用哈希表,所以今天我们就可以利用之前学习过的 哈希表的实现 ,来对C++STL库中的 unordered_set 和 unordered_map 进行模拟实现。1. unordered_set和unordered_map介绍 &emsp...
这与之前的map类似,插入函数返回一个键值对,键存放指针,对存放bool值,用来判断是否插入成功。 ✨unordered_set介绍 文档介绍,点击跳转 unordered_set与unordered_map类似,不同在于前者储存单个数据,后者储存键值对,这里就不过多介绍。 2. 修改哈希表 因为我们要使用哈希表来实现对unordered_set和...
对于指针类型,标准库只是单一将地址转换为一个size_t值作为hash值,这里特别需要注意的是char *类型的指针,其标准库提供的hash函数只是将指针所指地址转换为一个sieze_t值,如果,你需要用char *所指的内容做hash,那么,你需要自己写hash函数或者调用系统提供的hash<string>。
我们需要对哈希表指针和结点指针进行封装。 template<class K, class T, class Hash, class KeyOfT>class HashTable;template<class K, class T, class Hash, class KeyOfT>struct _HashIterator{typedef HashNode<T> Node;typedef HashTable<K, T, Hash, KeyOfT> HT;typedef _HashIterator<K, T, Hash, ...
所以插入的完整代码如下: 当key不是int类型而是string时,就不能取余数了。那该怎么办呢? 这里需要用到仿函数,如下图: 当key可以强转成整形时(比如负数,指针等),用缺省的仿函数即可。当key是string这种不能强转成整形的类型时,就要手动写一个转换成整形的仿函数。上方是取string的第一个字符进行返回。同时也要手...
迭代器需要前置声明HashTable,因为HashTable类中使用了__HTIterator迭代器,且__HTIterator中使用了HashTable类的指针,为什么要用指针呢? 因为C++编译器自上而下编译源文件的时候,对每一个数据的定义,需要知道定义的数据类型的大小。在预先声明语句class HashTable;之后,编译器已经知道HashTable是一个类,但是其中的数据...
set底层结构基于模板类class _Hash,其内部与unordered_multiset类似。MSVC2017的unordered_set采用开散列(拉链法)处理碰撞,维护一个链表list和一个存储每个哈希值对应链表首尾迭代器的数组vect。每个_Bucket是通过哈希计算得到的正整数值,vect的大小通常为key允许范围最大值的两倍,以存放_Bucket链表的指针...
迭代器是指向unordered_set中元素的指针,可以使用它们来访问和操作个别元素。 要访问unordered_set中的第一个元素,可以使用begin()函数: cpp std::unordered_set<int>::iterator itr = mySet.begin(); 这里创建了一个名为itr的unordered_set<int>迭代器,并将其指向mySet中的第一个元素。 要访问unordered_set...