当前位置: 首页 > news >正文

国外购物网站系统出入东莞最新通知今天

国外购物网站系统,出入东莞最新通知今天,wordpress不能发表,网站开发 常德一.核心源码分析这里我们对unordered_map/set的实现讲解细节上不会像之前那么多,因为具体的操作已经在红黑树封装map/set中讲解过。不过这里我们需要重点看看源码中的参数以及迭代器的问题。1.hash_set的头文件解析stl的SGI中unordered_set是以hash_set的名字命名的…

一.核心源码分析

这里我们对unordered_map/set的实现讲解细节上不会像之前那么多,因为具体的操作已经在红黑树封装map/set中讲解过。不过这里我们需要重点看看源码中的参数以及迭代器的问题。

1.hash_set的头文件解析

stl的SGI中unordered_set是以hash_set的名字命名的,不过功能上没有什么差异

它的参数分别为:键(Value),将非整型转为整型HashFcn,支持判断相等EqualKey,空间配置器Alloc。其实可以看到在这里的源码命名依旧十分混乱,我们只需要关注set和map本身存储的数据类型即可。

// stl_hash_set
template <class Value, class HashFcn = hash<Value>,
class EqualKey = equal_to<Value>,
class Alloc = alloc>
class hash_set
{ 
private:
typedef hashtable<Value, Value, HashFcn, identity<Value>,
EqualKey, Alloc> ht;
ht rep;
public:
typedef typename ht::key_type key_type;
typedef typename ht::value_type value_type;
typedef typename ht::hasher hasher;
typedef typename ht::key_equal key_equal;
typedef typename ht::const_iterator iterator;
typedef typename ht::const_iterator const_iterator;
hasher hash_funct() const { return rep.hash_funct(); }
key_equal key_eq() const { return rep.key_eq(); }
};

2.hash_map的头文件解析

这里的参数类型和上面的hash_set没有什么不同。map我们都知道存储的是一个键值对的pair类型。

// stl_hash_map
template <class Key, class T, class HashFcn = hash<Key>,
class EqualKey = equal_to<Key>,
class Alloc = alloc>
class hash_map
{ 
private:
typedef hashtable<pair<const Key, T>, Key, HashFcn,
select1st<pair<const Key, T> >, EqualKey, Alloc> ht;
ht rep;
public:
typedef typename ht::key_type key_type;
typedef T data_type;
typedef T mapped_type;
typedef typename ht::value_type value_type;
typedef typename ht::hasher hasher;
typedef typename ht::key_equal key_equal;
typedef typename ht::iterator iterator;
typedef typename ht::const_iterator const_iterator;
}

3.HashTable的头文件解析

和之前讲红黑树封装实现map/set一样,为了实现泛型编程的目的——用一份HashTable同时支持实现unordered_set/map。我们可以看结点类hashtable_node,存储一个hashtable_node的指针,以及数据val,val既可能是set的键类型,也可能是map的pair类型。

// stl_hashtable.h
template <class Value, class Key, class HashFcn,
class ExtractKey, class EqualKey,
class Alloc>
class hashtable {
public:
typedef Key key_type;
typedef Value value_type;
typedef HashFcn hasher;
typedef EqualKey key_equal;
private:
hasher hash;
key_equal equals;
ExtractKey get_key;
typedef __hashtable_node<Value> node;
vector<node*,Alloc> buckets;
size_type num_elements;
public:
typedef __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey,
Alloc> iterator;
pair<iterator, bool> insert_unique(const value_type& obj);
const_iterator find(const key_type& key) const;
}template <class Value>
struct __hashtable_node
{
__hashtable_node* next;
Value val;
};

二.unordered_set/map实现

1.HashTable的迭代器

之前我们写的HashTable,构造,析构,拷贝和迭代器还没有解决,这里重点讲解这些知识。

先来说迭代器。

这个迭代器的思路也比较简单,先讲最重要的operator++的逻辑。如果当前结点所在的桶还有下一个结点,就继续遍历

if (_node->_next)
{_node = _node->_next;
}

当前桶已遍历完,取到当前桶的hashi,从++hashi开始找不为空的桶

else
{KeyOfT kot;Hash hash;size_t hashi = hash(kot(_node->_data)) % _ht->_tables.size();++hashi;// ... 后续代码
}

开始查找下一个不为空的桶

while (hashi < _ht->_tables.size())
{_node = _ht->_tables[hashi];if (_node)break;  // 找到非空桶else++hashi; // 继续查找下一个桶
}

如果把所有桶都遍历完,就指向迭代器的end位置(nullptr)

if (hashi == _ht->_tables.size())
{_node = nullptr;
}

完整的operator++的代码

Self& operator++()
{if (_node->_next){// 当前桶还有数据,走到当前桶下一个节点_node = _node->_next;}else{// 当前桶走完了,找下一个不为空的桶KeyOfT kot;Hash hash;size_t hashi = hash(kot(_node->_data)) % _ht->_tables.size();++hashi;while (hashi < _ht->_tables.size()){_node = _ht->_tables[hashi];if (_node)break;else++hashi;}// 所有桶都走完了,end()给的空标识的_nodeif (hashi == _ht->_tables.size()){_node = nullptr;}}return *this;
}

那么begin位置和end位置迭代器的逻辑也很容易能得出:

//begin就是找到第一个不为空的桶
Iterator Begin()
{if (_n == 0)return End();for (size_t i = 0; i < _tables.size(); i++){    //从哈希表的0位置开始找Node* cur = _tables[i];//不为空的桶if (cur){return Iterator(cur, this);}}return End();
}//end位置就是一个nullptr
Iterator End()
{return Iterator(nullptr, this);
}

完整的迭代器:需要注意的一点是这里我们加上了HashTable的前置声明,因为迭代器中需要它的哈希表指针,如果不加前置声明编译器不认识HashTable是什么。

// 前置声明
template<class K, class T, class KeyOfT, class Hash>
class HashTable;template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>
struct HTIterator
{typedef HashNode<T> Node;typedef HashTable<K, T, KeyOfT, Hash> HT;typedef HTIterator<K, T, Ref, Ptr, KeyOfT, Hash> Self;Node* _node;const HT* _ht;HTIterator(Node* node, const HT* ht):_node(node),_ht(ht){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator!=(const Self& s){return _node != s._node;}Self& operator++(){if (_node->_next){// 当前桶还有数据,走到当前桶下一个节点_node = _node->_next;}else{// 当前桶走完了,找下一个不为空的桶KeyOfT kot;Hash hash;size_t hashi = hash(kot(_node->_data)) % _ht->_tables.size();++hashi;while (hashi < _ht->_tables.size()){_node = _ht->_tables[hashi];if (_node)break;else++hashi;}// 所有桶都走完了,end()给的空标识的_nodeif (hashi == _ht->_tables.size()){_node = nullptr;}}return *this;}};

2.对HashTable的处理

这里的处理其实就跟对RBTree的处理一样了。无非就是把该支持的仿函数加上,然后支持泛型即可。析构函数的逻辑就是一个桶一个桶,一个一个结点释放的。

template<class K, class T, class KeyOfT, class Hash>
class HashTable
{// 友元声明template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>friend struct HTIterator;typedef HashNode<T> Node;
public:typedef HTIterator<K, T, T&, T*, KeyOfT, Hash> Iterator;typedef HTIterator<K, T, const T&, const T*, KeyOfT, Hash> ConstIterator;Iterator Begin(){if (_n == 0)return End();for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];if (cur){return Iterator(cur, this);}}return End();}Iterator End(){return Iterator(nullptr, this);}ConstIterator Begin() const{if (_n == 0)return End();for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];if (cur){return ConstIterator(cur, this);}}return End();}ConstIterator End() const{return ConstIterator(nullptr, this);}HashTable():_tables(__stl_next_prime(0)), _n(0){}// 拷贝构造和赋值重载也需要~HashTable(){for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){Node* next = cur->_next;delete cur;cur = next;}_tables[i] = nullptr;}}pair<Iterator, bool> Insert(const T& data){KeyOfT kot;Iterator it = Find(kot(data));if (it != End())return { it, false};Hash hash;// 负载因子 == 1时扩容if (_n == _tables.size()){/*HashTable<K, V> newht;newht._tables.resize(__stl_next_prime(_tables.size() + 1));for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){newht.Insert(cur->_kv);cur = cur->_next;}}_tables.swap(newht._tables);*/vector<Node*> newTable(__stl_next_prime(_tables.size()+1));for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){Node* next = cur->_next;// 头插到新表size_t hashi = hash(kot(cur->_data)) % newTable.size();cur->_next = newTable[hashi];newTable[hashi] = cur;cur = next;}_tables[i] = nullptr;}_tables.swap(newTable);}size_t hashi = hash(kot(data)) % _tables.size();// 头插Node* newnode = new Node(data);newnode->_next = _tables[hashi];_tables[hashi] = newnode;++_n;return { Iterator(newnode, this), false };}Iterator Find(const K& key){KeyOfT kot;Hash hash;size_t hashi = hash(key) % _tables.size();Node* cur = _tables[hashi];while (cur){if (kot(cur->_data) == key){return Iterator(cur, this);}cur = cur->_next;}return End();}bool Erase(const K& key){KeyOfT kot;size_t hashi = key % _tables.size();Node* prev = nullptr;Node* cur = _tables[hashi];while (cur){if (kot(cur->_data) == key){if (prev == nullptr){// 头结点_tables[hashi] = cur->_next;}else{// 中间节点prev->_next = cur->_next;}delete cur;--_n;return true;}else{prev = cur;cur = cur->_next;}}return false;}
private:vector<Node*> _tables; // 指针数组size_t _n = 0;		   // 表中存储数据个数//struct Data//{//	ListNode* _head;//	RBTreeNode* _root;//	size_t _len;  // <= 8 存链表,>8 存红黑树 //};//vector<Data> _tables;//size_t _n = 0;		   // 表中存储数据个数//struct Data//{//	list<pair<K, V>> _list;//	map<K, V> _map;//	size_t _len;  // <= 8 存链表,>8 存红黑树 //};//vector<Data> _tables;//size_t _n = 0;		   // 表中存储数据个数
};

3.unordered_set实现

#pragma once#include"HashTable.h"namespace bit
{template<class K, class Hash = HashFunc<K>>class unordered_set{struct SetKeyOfT{const K& operator()(const K& key){return key;}};public:typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::Iterator iterator;typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::ConstIterator const_iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}pair<iterator, bool> insert(const K& key){return _ht.Insert(key);}iterator Find(const K& key){return _ht.Find(key);}bool Erase(const K& key){return _ht.Erase(key);}private:hash_bucket::HashTable<K, const K, SetKeyOfT, Hash> _ht;};

4.unordered_map实现

注意这里unordered_map的逻辑也是复用了Insert的逻辑,具体了解可以移步红黑树封装实现map/set。

#pragma once#include"HashTable.h"// MyUnorderedMap.h
namespace bit
{template<class K, class V, class Hash = HashFunc<K>>class unordered_map{struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::Iterator iterator;typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::ConstIterator const_iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}V& operator[](const K& key){pair<iterator, bool> ret = insert({ key, V() });return ret.first->second;}pair<iterator, bool> insert(const pair<K, V>& kv){return _ht.Insert(kv);}iterator Find(const K& key){return _ht.Find(key);}bool Erase(const K& key){return _ht.Erase(key);}private:hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash> _ht;};

http://www.dtcms.com/a/541539.html

相关文章:

  • 如何删除 AEDT 中的排队模拟?
  • 做网站的公司面试邢台企业建站
  • 万站群cms平台怎么推广技巧
  • 一加13/13T手动偷渡ColorOS16系统-享受德芙丝滑+增量包下载
  • 数据结构——三十二、最短路径问题——BFS算法(王道408)
  • 最新的高端网站建设网站结构方面主要做哪些优化
  • 电子商务静态网站建设心得网站服务合同用交印花税吗
  • Day.js 使用文档
  • 云栖实录 | 阿里云助力金山办公打造智能搜索新标杆:WPS云文档搜索技术全面升级
  • 监利网站建设国外互动网站
  • docker离线镜像文件选择导入脚本
  • Lua-迭代器
  • 社交网站 设计单仁营销网站的建设
  • RT-Thread FAL:为何NOR Flash必须注册为MTD设备?——深入解析RTOS设备模型
  • 如何查看网站蜘蛛数码公司网站建设的意义
  • 在婚恋网站做销售好吗网站推广排名哪家公司好
  • C#实现与欧姆龙PLC通信
  • 沧州瑞智网站建设一键优化下载安装
  • 网站源码带数据南充网站设计学校
  • 东莞高端品牌网站建设湛江网站建设托管
  • yolov5代码
  • wordpress首页文字广告框架在线seo
  • Rust:复合类型
  • Vue 3 + Element Plus 动态表格高度自适应方案详解
  • python flask简单使用
  • 课外辅导东莞网站建设技术支持saas系统是什么样的系统
  • 【论文精读】DeepSeek-OCR:探索视觉 - 文本压缩的新范式
  • 成都市网站设中国能源建设集团网站群
  • k8s 容器部署
  • Android的事件分发机制