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

网站开发的背景与环境四川省建设厅燃气网站

网站开发的背景与环境,四川省建设厅燃气网站,地产项目网站建设ppt,ppt模板下载网站推荐目录 前言 KeyOfT 迭代器实现 解释 模板参数 const operator 其他运算符重载 begin和end insert和find operator[] unordered_set unordered_map 前言 在前两章中,我们详细介绍了哈希表的实现,而unordered_set与unordered_map的底层就是用到…

目录

前言

KeyOfT

迭代器实现

 解释

模板参数

const

operator++

其他运算符重载

begin和end

insert和find

operator[]

unordered_set

unordered_map


前言

在前两章中,我们详细介绍了哈希表的实现,而unordered_set与unordered_map的底层就是用到了哈希表,今天我们就用哈希表来封装我们的unordered_set与unordered_map。在此之前我们先来回顾一下之前写的哈希结构。

	template<class K, class V, class Hash = HashFunc<K>>class HashTable{typedef HashNode<K, V> Node;public:HashTable(){_tables.resize(10);}~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;}}bool Insert(const pair<K, V>& kv){if (Find(kv.first))return false;Hash hf;if (_n == _tables.size()){vector<Node*> newTables;newTables.resize(_tables.size() * 2, nullptr);// 遍历旧表for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while(cur){Node* next = cur->_next;// 挪动到映射的新表size_t hashi = hf(cur->_kv.first) % newTables.size();cur->_next = newTables[hashi];newTables[hashi] = cur;cur = next;}_tables[i] = nullptr;}_tables.swap(newTables);}size_t hashi = hf(kv.first) % _tables.size();Node* newnode = new Node(kv);// 头插newnode->_next = _tables[hashi];_tables[hashi] = newnode;++_n;return true;}Node* Find(const K& key){Hash hf;size_t hashi = hf(key) % _tables.size();Node* cur = _tables[hashi];while (cur){if (cur->_kv.first == key){return cur;}cur = cur->_next;}return NULL;}bool Erase(const K& key){Hash hf;size_t hashi = hf(key) % _tables.size();Node* prev = nullptr;Node* cur = _tables[hashi];while (cur){if (cur->_kv.first == key){if (prev == nullptr){_tables[hashi] = cur->_next;}else{prev->_next = cur->_next;}delete cur;return true;}prev = cur;cur = cur->_next;}return false;}private:vector<Node*> _tables;size_t _n = 0;};

 我们用开散列的方式实现了哈希表的insert、find、erase的功能,并且增加一个模板参数,引入一个仿函数,来实现对string类型的哈希转换处理。

KeyOfT

但是要想封装unordered_set与unordered_map还需要一个模板,因为像上面代码中的情况,只考虑了kv结构,符合unordered_map,但不符合unordered_set,难道我们要写两个哈希结构嘛?当然不是,我们只需要针对map和set写一个仿函数即可,然后再增加一个模板参数。这样,当我们使用unordered_set与unordered_map时只需要将各自的仿函数传入即可。

//unordered_map
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;}};private:hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash> _ht;};
//unordered_set
template<class K, class Hash = HashFunc<K>>class unordered_set{struct SetKeyOfT{const K& operator()(const K& key){return key;}};private:hash_bucket::HashTable<K, K, SetKeyOfT, Hash> _ht;};

 像上面两个代码中,分别实现了各自的仿函数,其实,只要是针对map进行了修改,因为他的类型是pair,在比较时只需要返回pair.first,set本身就可以比较,只是为了配合map写一个仿函数。这样就能避免写两份哈希结构的缺点。

迭代器实现

template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>struct __HTIterator{typedef HashNode<T> Node;typedef __HTIterator<K, T, Ref, Ptr, KeyOfT, Hash> Self;Node* _node;const HashTable<K, T, KeyOfT, Hash>* _pht;// vector<Node*> * _ptb;size_t _hashi;__HTIterator(Node* node, HashTable<K, T, KeyOfT, Hash>* pht, size_t hashi):_node(node),_pht(pht),_hashi(hashi){}Self& operator++(){if (_node->_next){// 当前桶还有节点,走到下一个节点_node = _node->_next;}else{// 当前桶已经走完了,找下一个桶开始//KeyOfT kot;//Hash hf;//size_t hashi = hf(kot(_node->_data)) % _pht._tables.size();++_hashi;while (_hashi < _pht->_tables.size()){if (_pht->_tables[_hashi]){_node = _pht->_tables[_hashi];break;}++_hashi;}if (_hashi == _pht->_tables.size()){_node = nullptr;}}return *this;}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator!=(const Self& s){return _node != s._node;}};
	template<class K, class T, class KeyOfT, class Hash>class HashTable{typedef HashNode<T> Node;template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>friend struct __HTIterator;public:typedef __HTIterator<K, T, T&, T*, KeyOfT, Hash> iterator;typedef __HTIterator<K, T, const T&, const T*, KeyOfT, Hash> const_iterator;iterator begin(){for (size_t i = 0; i < _tables.size(); i++){if (_tables[i]){return iterator(_tables[i], this, i);}}return end();}iterator end(){return iterator(nullptr, this, -1);}const_iterator begin() const{for (size_t i = 0; i < _tables.size(); i++){if (_tables[i]){return const_iterator(_tables[i], this, i);}}return end();}// this-> const HashTable<K, T, KeyOfT, Hash>*const_iterator end() const{return const_iterator(nullptr, this, -1);}HashTable(){_tables.resize(10);}~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){Hash hf;KeyOfT kot;iterator it = Find(kot(data));if (it != end())return make_pair(it, false);// 负载因子最大到1if (_n == _tables.size()){vector<Node*> newTables;newTables.resize(_tables.size() * 2, nullptr);// 遍历旧表for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while(cur){Node* next = cur->_next;// 挪动到映射的新表size_t hashi = hf(kot(cur->_data)) % newTables.size();cur->_next = newTables[i];newTables[hashi] = cur;cur = next;}_tables[i] = nullptr;}_tables.swap(newTables);}size_t hashi = hf(kot(data)) % _tables.size();Node* newnode = new Node(data);// 头插newnode->_next = _tables[hashi];_tables[hashi] = newnode;++_n;return make_pair(iterator(newnode, this, hashi), true);}iterator Find(const K& key){Hash hf;KeyOfT kot;size_t hashi = hf(key) % _tables.size();Node* cur = _tables[hashi];while (cur){if (kot(cur->_data) == key){return iterator(cur, this, hashi);}cur = cur->_next;}return end();}bool Erase(const K& key){Hash hf;KeyOfT kot;size_t hashi = hf(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;return true;}prev = cur;cur = cur->_next;}return false;}private:vector<Node*> _tables;size_t _n = 0;};
}

 

 解释

模板参数

 这是迭代器的实现,接下来我们详细解释一下:

template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>

首先我们注意到新增了Ref和Ptr两个模板,这两个模板能够帮助我们实现普通迭代器和const迭代器。这时对应我们的哈希表:

typedef __HTIterator<K, T, T&, T*, KeyOfT, Hash> iterator;
typedef __HTIterator<K, T, const T&, const T*, KeyOfT, Hash> const_iterator;

当我们传参时,可以通过T&、T*和const T&、 const T*来实现不同的迭代器,计算机会实例化出两个版本。

const

不同以往的迭代器,它里面不仅有节点的指针,还有哈希表的指针和当前所在的桶的位置。我们可以看到

const HashTable<K, T, KeyOfT, Hash>* _pht;

他用const进行了修饰,这是因为:

		// this-> const HashTable<K, T, KeyOfT, Hash>*const_iterator end() const{return const_iterator(nullptr, this, -1);}

在实现const版本时,this指针被修饰为了const,所以如果不将迭代器中的_pht进行const修饰,就会出现权限放大,这样是会报错的。

operator++

++比较好实现,分三种情况:

1.如果_node的next不为空,那么直接将_node赋值为_node的next.

2.如果为空,那么寻找下一个桶,直到下一个桶不为空时结束,将_node进行更改。

3.若找到最后还没有找到不为空的位置,直接将_node置空即可。

但是需要注意的是,我们在迭代器中用到了哈希表的私有成员,我们需要将它作为友元,而且我们需要在迭代器之前声明一下哈希表。否则会报错

	// 前置声明template<class K, class T, class KeyOfT, class Hash>class HashTable;

其他运算符重载

其他运算符重载比较简单,和平时的一样,不过多解释。

begin和end

返回头尾的迭代器。

insert和find

因为有了迭代器,所以这两个的返回值需要变化一下,也比较简单。

operator[]

		const V& operator[](const K& key) const{pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));return ret.first->second;}

 在unordered_map中有一个非常方便的用法就是[],这样就和我们平时的数组使用方法一样非常简单。它其实就是先进行插入在返回引用,方便我们对pair.second的值进行修改。

unordered_set

	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, K, SetKeyOfT, Hash>::const_iterator iterator;typedef typename hash_bucket::HashTable<K, K, SetKeyOfT, Hash>::const_iterator 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<const_iterator, bool> insert(const K& key){auto ret = _ht.Insert(key);return pair<const_iterator, bool>(const_iterator(ret.first._node, ret.first._pht, ret.first._hashi), ret.second);}iterator find(const K& key){return _ht.Find(key);}bool erase(const K& key){return _ht.Erase(key);}private:hash_bucket::HashTable<K, K, SetKeyOfT, Hash> _ht;};

 普通迭代器对于他来说可有可无,因为它不能对k值进行修改。

unordered_map

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;iterator begin(){return _ht.begin();}iterator end(){return _ht.end();}pair<iterator, bool> insert(const pair<K, V>& kv){return _ht.Insert(kv);}V& operator[](const K& key){pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));return ret.first->second;}const V& operator[](const K& key) const{pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));return ret.first->second;}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/wzjs/835680.html

相关文章:

  • 网站工程师是做什么的写过太原的网站
  • 运营派网站dede 网站地图 调用文章
  • 铜陵网站优化wordpress mysql 配置文件
  • 山东春季高考网站建设新能源汽车十大名牌
  • 网站设计步骤的教学设计动漫设计是什么
  • 写代码做网站学做吃的的网站
  • 什么网站程序可以做抽奖页面网站每天点击量多少好
  • 鞍山网站建设工作室咨询公司的成本费用有哪些
  • 网站设计需要学什么软件公关公司多少钱一个月
  • 网站建设公司介绍ppt做网站可以用php
  • 施工企业会计课后答案网站的优化从哪里进行
  • 太平鸟品牌门户网站建设天津建设工程网官网
  • 个人网站毕业设计最新国际要闻
  • 秸秆可以发酵吗网站建设吗网络营销工具的定义
  • 个人网站设计 优帮云互联网网站建设问卷调查
  • 图片网站 建站怎样做网络推广给我 你所有地方都上手
  • 购物 网站建设的市场分析申请免费建站
  • 企业型网站建设咨询电话wordpress jquery ui
  • 毕业设计2网站建设做宾馆网站好
  • 网站建设颜色搭配怎么在手机上做网站
  • 驻马店做网站的公司南宁小程序定制开发
  • 网站建设pad版本是什么学会wordpress后万能
  • 网站域名哪里买wordpress文章自动更新
  • 做电商卖玉器的网站网站规划与设计方向
  • 企业备案网站服务内容深圳专业网站设计专业定制
  • wordpress 嵌套插件做网站优化有前景吗
  • 横栏网站建设信息发布网站建设
  • 免费建立微网站屏蔽网站ip
  • a站进入商品展示介绍网站源码
  • 好的网站设计网站注册域名备案