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

网站做三方登陆需要注册公司不网站提现功能怎么做

网站做三方登陆需要注册公司不,网站提现功能怎么做,二维码转短链接生成器,网站验证钱的分录怎么做目录 前言: 一:修改参数 二:实现迭代器 三:实现运算符重载 四:其他运算符的重载 五:实现begin和end 六:实现const类型迭代器 七:修改Insert返回值 八:重载map的…

目录

前言:

一:修改参数

二:实现迭代器

三:实现++运算符重载

四:其他运算符的重载

五:实现begin和end

六:实现const类型迭代器 

七:修改Insert返回值

八:重载map的 [ ] 

九:修改HashFunc仿函数

总结:


前言:

我们之前已经讲到过哈希表是如何实现了,相信追剧的小伙伴C++功底已经突飞猛进了,在底层中,不仅有map和set,还有unordered_set和unordered_map,底层正是用我们之前写的哈希表实现的(本篇会跳过很多细节,因为之前已经讲过封装,可以看这篇博客:【C++】通过红黑树封装map和set-CSDN博客)。

这里我们就用之前的哈希表代码,继续在上面封装,将其封装为unordered_set和unordered_map。和红黑树封装一样,内容劲爆,老铁焖做好心理准备,我们开始了!

一:修改参数

还是和之前一样,这里已经做好了它们的头文件,之后需要三个参数,而对于HashTable需要再多加一个模板参数,也就是KeyOfT。KeyOfT的作用就是找是K还是pair的first。我们给出unorderedSet头文件代码:

#pragma once
#include"myHash.h"namespace bit
{template<class K>class unordered_set{public:struct SetOfK{const K& operator()(const K& key){return key;}};//插入函数bool insert(const K& key){return _ht.Insert(key);}//删除函数bool erase(const K& key){return _ht.Erase(key);}private:hash_bucket::HashTable<K, K, SetOfK> _ht;};
}

map如下:

#include"myHash.h"namespace bit
{template<class K, class V>class unordered_map{public:struct MapOfK{const K& operator()(const pair<K, V>& kv){return kv.first;}};//插入函数bool insert(const pair<K, V>& kv){return _ht.Insert(kv);}//删除函数bool erase(const K& key){return _ht.Erase(key);}private:hash_bucket::HashTable<K, pair<K, V>, MapOfK> _ht;};
}

这里修改参数应该难不倒各位同学,接下来我们实现迭代器。

二:实现迭代器

我们已经有了之前的经验,迭代器我们通过一个类来实现,所以这次我们直接声明迭代器类(本质还是指针)。

template<class T>
struct HashTableIterator
{using Node = HashNode<T>;using Self = HashTableIterator; //这里可以不写模板参数//构造函数HashTableIterator(Node* node): _node(node){}Node* _node;
};

三:实现++运算符重载

我们是否可以直接让_node = _node->_next就行了呢?

可以看出,这样不行,当前链表走完了,下一步怎么办?此时我们还没有拿到哈希表最开始位置的指针,这时我们需要将哈希表对象指针传递过来。 

template<class T>
struct HashTableIterator
{using Node = HashNode<T>;using Self = HashTableIterator; //这里可以不写模板参数HashTable<K, T, KeyOfT>* _pht;//构造函数HashTableIterator(Node* node): _node(node){}Node* _node;
};

这里是不行的,首先迭代器中的HashTable的这些模板参数根本无法获取,我们必须在HashTableIterator的模板参数中提供。但是此时我们的HashTable在迭代器下方声明定义,编译器器无法识别,所以要在其上面添加其声明。最后我们就算拿到了HashTable的指针,但是我们无法访问其私有成员_table,所以在HashTable中将其声明为友元函数。

并且修改迭代器的构造方法,使其能拿到对应指针;当然因为会重新计算hashi,所以我们需要增加KeyOfT的实例化对象,这里就是kot。

而且我们上面声明了HashTable,在迭代器中使用就要把所有参数都加上,所以我们需要给迭代器再多加一个模板参数——Hash;当然不排除string类型,把Hash也实例化一个对象hs。

//声明HashTable 此时模板参数不需要加缺省值
template<class K, class T, class KeyOfT, class Hash>
class HashTable;template<class K, class T, class KeyOfT, class Hash>
struct HashTableIterator
{using Node = HashNode<T>;using Self = HashTableIterator; //这里可以不写模板参数KeyOfT kot; //为了计算hashiHash hs;HashTable<K, T, KeyOfT, Hash>* _pht;//构造函数HashTableIterator(Node* node, HashTable<K, T, KeyOfT, Hash>* pht): _node(node), _pht(pht){}Node* _node;
};

在HashTable中添加声明友元类(先写模板参数,之后友元声明):

template<class K, class T, class KeyOfT, class Hash = HashFunc<K>>
class HashTable
{
public:using Node = HashNode<T>;//声明成友元类 先写模板参数template<class K, class T, class KeyOfT, class Hash>friend struct HashTableIterator;//...
};

此时我们就可以完善++了,我们先判断是否还有_next,否则就根据_node重新计算hashi。

Self& operator++()
{if (_node->_next){_node = _node->_next;}else{//重新计算hashisize_t hashi = hs(kot(_node->_data)) % _pht->_table.size();++hashi; //跳过当前桶while (hashi < _pht->_table.size()){if (_pht->_table[hashi]){//此时遇到不为空的节点_node = _pht->_table[hashi];break;}++hashi;}//当然会走到空if (hashi == _pht->_table.size()){_node = nullptr;}}return *this;
}

四:其他运算符的重载

接下来我们实现 != 、== 、* 、-> 这些运算符的重载:

bool operator==(const Self& s)
{return _node == s._node;
}bool operator!=(const Self& s)
{return _node != s._node;
}T& operator*()
{return _node->_data;
}T* operator->()
{return &_node->_data;
}

因为它们太简单了,这里不多做解释。

五:实现begin和end

我们要实现begin和end,先把HashTable的Begin和End实现,Begin就是找第一个不为空的桶;End和之前一样直接拿空构造即可。因为迭代器需要两个参数的构造方法,第二个参数是HashTable的指针,所以我们传入this即可:

//先将其重命名为 Iterator
typedef HashTableIterator<K, T, KeyOfT, Hash> Iterator;//定义Begin
Iterator Begin()
{//找到一个元素for (size_t i = 0; i < _table.size(); ++i){if (_table[i]){return Iterator(_table[i], this);}}//此时没有元素 返回End即可return End();
}//定义End
Iterator End()
{return Iterator(nullptr, this);
}

之后再map和set中实现begin和end,但是此前先对hash_backet的HashTable的Iterator为iterator(有点绕,不过很简单),在set中:

//先重命名
typedef typename hash_bucket::HashTable<K, K, SetOfK>::Iterator iterator;iterator begin()
{return _ht.Begin();
}iterator end()
{return _ht.End();
}

六:实现const类型迭代器 

大家知道,按照传统艺能,我们接下来就要将其改变为能够遍历const类型数据的迭代器了,具体细节可以看【C++】通过红黑树封装map和set-CSDN博客 小编的这篇博客,里面对为什么使用以下方法作出了很详细的解释。

还是和之前一样,对迭代器多提供两个参数,一个是引用,一个是指针即可。因为只有 * 和 -> 两个运算符重载返回类型不一样。

template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>
struct HashTableIterator
{//...Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}Node* _node;
};

所以此时在HashTable中我们这样定义迭代器:

typedef HashTableIterator<K, T, T&, T*, KeyOfT, Hash> Iterator;
typedef HashTableIterator<K, T, const T&, const T*, KeyOfT, Hash> ConstIterator; 

记得我们之前定义的友元迭代器时要多加上两个参数:

//声明成友元类 先写模板参数
template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>
friend struct HashTableIterator;

这里我们就可以实现const版本的Begin和End了。

ConstIterator Begin() const
{for (size_t i = 0; i < _table.size(); ++i){if (_table[i]){return ConstIterator(_table[i], this);}}return End();
}ConstIterator End() const
{return ConstIterator(nullptr, this);
}

之后去完善set中的const版本迭代器:

typedef typename hash_bucket::HashTable<K, K, SetOfK>::Iterator iterator;
typedef typename hash_bucket::HashTable<K, K, SetOfK>::ConstIterator const_iterator;//... 以下为const版本
const_iterator begin() const
{return _ht.Begin();
}const_iterator end() const
{return _ht.End();
}

之后传统艺能,写一个函数来测试,参数是const类型,之后你就发现编译报错了(注意,这里不是一堆报错,只有一个),你双击错误发现停留在HashTable的const版本的End方法中,这是为什么?

这就是我们使用const时,End构造迭代器时,传入的this也是const版本,所以我们在迭代器中需要把_pht指针加上const修饰。记得把构造函数中的 _pht*也加上const修饰。

const HashTable<K, T, KeyOfT, Hash>* _pht;//构造函数
HashTableIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht): _node(node), _pht(pht)
{}

之后再次运行代码就不会有问题了。

七:修改Insert返回值

追剧的同学都知道,Insert返回的值可不是bool,而是一个pair类型。其具体细节可以参考【C++】认识map和set-CSDN博客 这篇文章。

所以这里和之前修改代码是致的:

pair<Iterator, bool> Insert(const T& data)
{//先复用Find//Node* ret = Find(kv.first);Node* ret = Find(kot(data));  //这里要找的是Kif (ret){//存在 无需插入return make_pair(Iterator(ret, this), false);}//...return make_pair(Iterator(newNode, this), true);
}

之后修改set和map中的insert即可。

八:重载map的 [ ] 

这里 [ ] 是复用的insert,具体细节可以看【C++】通过红黑树封装map和set-CSDN博客 这篇文章,这里不再赘述,直接上代码:

V& operator[](const K& key)
{iterator it = insert(make_pair(key, V())).first;return it->second;
}

九:修改HashFunc仿函数

如果我们传入的是指针该怎么办?我们应该修改HashFunc这个仿函数,但是我们目前的map和set类中没有这个模板参数,其模板参数在HashTable中,但是我们又不可能跳过map和set给HashTable传入这个仿函数,所以就有问题,我们在写HashTable的时候最后的Hash模板参数不能提供默认的参数,否则有问题,所以我们应该对set和map增加模板参数。

//这里提供第三个默认模板参数
template<class K, class V, class Hash = HashFunc<K>>
class unordered_map
{//...typedef typename hash_bucket::HashTable<K, pair<K, V>, MapOfK, Hash>::Iterator iterator;typedef typename hash_bucket::HashTable<K, pair<K, V>, MapOfK, Hash>::ConstIterator const_iterator;//...
private:hash_bucket::HashTable<K, pair<K, V>, MapOfK, Hash> _ht;
};

因为我们已经把HashFunc写为全局函数了,所以就这样使用,把HashTable中的缺省模板参数删除即可。

总结:

终于又解决了一个大问题,这里我们C++的水平应该就很强了,之后我们要学习一些有关C++11的新特性,并进入Linux篇,继续学习关于信号等知识,大家敬请期待吧!


文章转载自:

http://4URLnxL5.tLpgp.cn
http://Qla5LM5z.tLpgp.cn
http://qK1AH0ut.tLpgp.cn
http://m6sjnRxs.tLpgp.cn
http://eO7YM9QZ.tLpgp.cn
http://91UpnPDZ.tLpgp.cn
http://fI5hs2dn.tLpgp.cn
http://YkWY4oAO.tLpgp.cn
http://Op1RjfPH.tLpgp.cn
http://1rRsBDF1.tLpgp.cn
http://LPs5jAU2.tLpgp.cn
http://sELqTZbK.tLpgp.cn
http://c4IRZ3X1.tLpgp.cn
http://9ScxOivw.tLpgp.cn
http://9CvuiZoy.tLpgp.cn
http://xs20lct3.tLpgp.cn
http://pGxAHc3k.tLpgp.cn
http://bnvHk3pg.tLpgp.cn
http://SaP51GkV.tLpgp.cn
http://lVZ4C3Tw.tLpgp.cn
http://YNlxlzQV.tLpgp.cn
http://LSkkYV0Z.tLpgp.cn
http://nViIN2qw.tLpgp.cn
http://FNEiGEbD.tLpgp.cn
http://6KpVJCRS.tLpgp.cn
http://YtgLP5Bi.tLpgp.cn
http://HIpaVtkD.tLpgp.cn
http://XjulJvdA.tLpgp.cn
http://WFMViYvo.tLpgp.cn
http://5mnmxzQW.tLpgp.cn
http://www.dtcms.com/wzjs/657003.html

相关文章:

  • 丰县住房与城乡建设部网站宁波百度推广优化
  • 做资讯网站需要哪些资质如何网站推广
  • 收录网站排名新生活cms订货系统下载
  • 房产集团公司网站建设方案延吉市建设局网站
  • 青岛小型网站建设最适合穷人的四种保险
  • 购物网站建设模板图片h5免费制作平台易企秀
  • 重庆市工程建设信息网新网站网页制作与设计在哪搜题
  • 海南专业网站运营托管百度收录网站但首页快照不更新
  • 网站建设 十佳制作老薛主机 wordpress
  • 静态网站开发课程网安徽网站建设制作
  • 用wordpress建站的好处wordpress 更改中文
  • 公司网站域名过期wordpress禁止更新代码
  • 珠海网站建设费用免费公司网站建设
  • 自己做的网站和ie不兼容点击最多的网站
  • 我的网站是面向全国的选哪个公司的服务器比较好佛山搜索引擎推广服务好
  • 网站集群建设的意义学历提升文案
  • 心理学门户网站开发与实现浙江网站推广公司
  • 网站备案用户注销备案申请表wordpress 收费下载资源
  • git做网站根目录网站被百度蜘蛛爬了多久放出来
  • 明星个人网站设计模板哈尔滨网站建设 熊掌号
  • 蓟县集团网站建设网页设计和网站开发哪个好
  • 河北建设厅查询官方网站如何设计制作企业网站
  • 网站建设合同百度文库丹棱县 网站建设
  • 北京网站制作服务佛山新网站建设详细内容
  • 面向网站开发的相关知识大连做网站排名
  • 淘宝联盟怎么自己做网站推广国际新闻最新消息今天新闻大事件 中方
  • 网站被管理员权限淘宝店铺购买价格
  • 最快网站备案企业文化建设内容主要包括
  • 长沙有家具网站建设的吗wordpress 5开发接口
  • 深圳微交易网站开发免费的正能量视频素材网站