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

省级精品课程网站百度竞价什么意思

省级精品课程网站,百度竞价什么意思,济南网站建设大标网络,企业 网站 客户留言怎么做前言:由于STL容器库提供的这两个容器的用法和其他容器差不多,用法方面我只会提一嘴,中心 放在模拟实现上 1. unordered_map unordered_map 是一个关联容器,用于存储键值对(key-value)的集合…

前言:由于STL容器库提供的这两个容器的用法和其他容器差不多,用法方面我只会提一嘴,中心             放在模拟实现上

1.  unordered_map

unordered_map 是一个关联容器,用于存储键值对(key-value)的集合。它的键(key)是唯一的,每个键对应一个值(value)。unordered_map 的查找、插入和删除操作的平均时间复杂度为 O(1)

特点

  • 无序性:元素存储的顺序与插入顺序无关,由哈希函数决定。

  • 唯一键:每个键在容器中只能出现一次。

  • 高效查找:通过哈希表实现,查找效率高。

适用场景

  • 需要快速查找、插入和删除键值对的场景。

  • 键需要唯一且无序的场景。

参考代码

#include<iostream>
#include<unordered_map>
using namespace std;
int main()
{unordered_map<int, string> umap;umap.insert({ 1, "Apple" });umap[2] = "Banana"; // 另一种插入方式for (auto& pair : umap){cout << pair.first << ": " << pair.second << endl;}if (umap.find(1) != umap.end()) {cout << umap[1]; // 输出 "Apple"}umap.erase(1); // 删除键为 1 的元素for (auto& pair : umap) {cout << pair.first << ": " << pair.second << endl;}return 0;
}

 2.unordered_set

unordered_set 是一个关联容器,用于存储唯一的键值集合。它与 unordered_map 类似,但只存储键(没有值)。unordered_set 的查找、插入和删除操作的平均时间复杂度也为 O(1)

特点

  • 无序性:元素存储的顺序与插入顺序无关。

  • 唯一性:每个键只能出现一次。

  • 高效查找:通过哈希表实现,查找效率高。

适用场景

  • 需要快速判断某个元素是否存在的场景。

  • 需要存储唯一元素的场景。

 参考代码: 

#include <iostream>
#include <unordered_set>int main() {std::unordered_set<int> uset;uset.insert(1);uset.insert(3);uset.insert(2);// 遍历for (const auto& elem : uset) {std::cout << elem << " " ;}std::cout << std::endl;// 查找if (uset.count(2)) {std::cout << "2 exists in the set" << std::endl;}// 遍历for (const auto& elem : uset) {std::cout << elem << " ";}// 删除uset.erase(2);// 遍历for (const auto& elem : uset){std::cout << elem << " ";}std::cout << std::endl;std::cout << std::endl;return 0;
}

 

3. unordered_map 和 unordered_set 的区别

特性unordered_mapunordered_set
存储内容键值对(key-value唯一的键值
插入操作插入键值对插入单个值
查找操作通过键查找对应的值判断某个值是否存在
适用场景需要存储键值对的场景需要存储唯一值的场景

4. 性能注意事项

  • 哈希冲突:如果哈希函数设计不好,可能会导致哈希冲突,降低性能。

  • 负载因子unordered_mapunordered_set 有一个负载因子(load factor),表示哈希表中元素数量与桶数量的比例。当负载因子过高时,容器会自动重新哈希(rehash),这会增加时间开销。

  • 自定义哈希函数:如果默认的哈希函数不满足需求,可以自定义哈希函数。

5.总结

  • unordered_map:适用于需要存储键值对的场景,查找、插入和删除效率高。

  • unordered_set:适用于需要存储唯一值的场景,判断元素是否存在效率高。

两者都基于哈希表实现,因此在需要高效查找的场景下非常有用。

 6.二者的模拟实现

6.1  改造hstable.h文件

由于二者都是基于哈希结构来实现的,所以我们可以将上节课的哈希桶的内容拿出来稍加改造,加入迭代器,并重载一下++,*,->等运算符,实现一下begin(),end()函数等等,要包括iterator和const_iterator,这里直接给出改造后的代码,读者可以根据需要选择性阅读!

这是改造后的hstable文件(原哈希桶文件) 

#pragma once
#include<iostream>
#include<vector>
using namespace std;
static const int __stl_num_primes = 28;
static const unsigned long __stl_prime_list[__stl_num_primes] =
{53,         97,         193,       389,       769,1543,       3079,       6151,      12289,     24593,49157,      98317,      196613,    393241,    786433,1572869,    3145739,    6291469,   12582917,  25165843,50331653,   100663319,  201326611, 402653189, 805306457,1610612741, 3221225473, 4294967291
};inline unsigned long __stl_next_prime(unsigned long n)
{const unsigned long* first = __stl_prime_list;const unsigned long* last = __stl_prime_list + __stl_num_primes;const unsigned long* pos = lower_bound(first, last, n);return pos == last ? *(last - 1) : *pos;
}template<class K>
struct HashFunc
{size_t operator()(const K& key){return (size_t)key;}
};template<>
struct HashFunc<string>
{size_t operator()(const string& key){size_t hashi = 0;for (auto ch : key){hashi *= 131;hashi += ch;}return hashi;}
};
namespace hash_bucket
{template<class T>struct HashNode{T _data;HashNode<T>* _next;HashNode(const T& data):_data(data), _next(nullptr){}};// 前置声明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;}Self& operator++(){if (_node->_next)     //当前桶不为空{// 当前桶向前走_node = _node->_next;}else{// 找下一个桶的第一个节点KeyOfT kot;Hash hs;size_t hashi = hs(kot(_node->_data)) % _ht->_tables.size();++hashi;while (hashi < _ht->_tables.size()){if (_ht->_tables[hashi]){_node = _ht->_tables[hashi];break;}else{++hashi;}}// 所有桶都走完了,nullptr去做end()if (hashi == _ht->_tables.size())_node = nullptr;}return *this;}bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}};//pair<const K, V>template<class K, class T, class KeyOfT, class Hash>class HashTable{// 友元声明   hash_bucket::HashTable<K, pair<const K, V>, MapKetofT, Hash>::Iterator iterator;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(){// 找第一个不为空的桶里面的第一个节点for (size_t i = 0; i < _tables.size(); i++){if (_tables[i]){return Iterator(_tables[i], this);}}return End();             //没找到默认返回末尾}Iterator End(){return Iterator(nullptr, this);}ConstIterator begin() const{// 找第一个不为空的桶里面的第一个节点for (size_t i = 0; i < _tables.size(); ++i){if (_tables[i]){return ConstIterator(_tables[i], this);}}return End();}ConstIterator End() const{return ConstIterator(nullptr, this);}HashTable(size_t size=__stl_next_prime(0)):_tables(size,nullptr){}~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) //这里说的有问题 就是const的{KeyOfT kot;Iterator it = Find(kot(data)); //大写if (it != End()){//说明原来的哈希表已经有这个数据了,插入失败return { it,false };}Hash hs;// 负载因子到1,再扩容if (_n == _tables.size()){// 也可以,但是扩容新开辟节点,释放旧节点,有点浪费/*HashTable<K, V> newHT(__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*> newtables(__stl_next_prime(_tables.size() + 1), nullptr);for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];    //挨个访问原表中的数据,要进行转移while (cur){// 旧表的节点挪动下来// 插入到映射的新表位置Node* next = cur->_next;size_t hashi = hs(kot(cur->_data)) % newtables.size();cur->_next = newtables[hashi];cur = next;}_tables[i] = nullptr;}_tables.swap(newtables);}size_t hashi = hs(kot(data)) % _tables.size();Node* newnode = new Node(data);// 头插newnode->_next = _tables[hashi];_tables[hashi] = newnode;++_n;//// 		HTIterator(Node* node, const HT* ht)//      :_node(node)///	      , _ht(ht)////return { {newnode,this},true };return make_pair(Iterator(newnode, this), true);}Iterator Find(const K& key){KeyOfT kot;Hash hs;size_t hashi = hs(key) % _tables.size();Node* cur = _tables[hashi];         //_tables[hashi]可以理解为链表的第一个数while (cur){if (kot(cur->_data) == key){return Iterator(cur, nullptr);}cur = cur->_next;}return End();}bool Erase(const K& key){KeyOfT kot;Hash hs;size_t hashi = hs(key) % _tables.size();Node* cur = _tables[hashi];Node* prev = nullptr;while (cur){if (kot(cur->_data) == key){//删除,但是要保证不影响这个桶的其他结点if (prev == nullptr){_tables[hashi] = cur->_next;}else{prev->_next = cur->_next;}--_n;delete cur;return true;}prev = cur;cur = cur->_next;}return false;}private:vector<Node*> _tables;size_t _n = 0;};
}

6.2 编写unorderedmap.h文件

由于我们在模拟实现一个容器,那()运算符是必不可少的,这里我们对数据的操作都是要对键进行操作的,所以我们运算符重载一下Operator(),取键值

		struct MapKetofT{const K& operator()(const pair<K, V>& kv){return kv.first;}};

 然后我们把begin(),end(),insert()等函数封装一下,

		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 pair<K, V>& kv) //pait<string, string>&{return _ht.Insert(kv);}V& operator[](const K& key){pair<iterator, bool> ret = _ht.Insert({ key,V() });return ret.first->second;}

最后是汇总代码以及测试文件:

 

#pragma once
#include"hstable.h"
#include<string>namespace rens
{template<class K, class V, class Hash = HashFunc<K>>class um{struct MapKetofT{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKetofT, Hash>::Iterator iterator;typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKetofT, 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 pair<K, V>& kv) //pait<string, string>&{return _ht.Insert(kv);}V& operator[](const K& key){pair<iterator, bool> ret = _ht.Insert({ key,V() });return ret.first->second;}private:hash_bucket::HashTable<K, pair<const K, V>, MapKetofT, Hash> _ht; //写错了};
}void test_unordered_map()
{rens::um<string, string> dict;dict.insert({ "string"," " });dict.insert({ "left", "" });dict["sort"];dict["left"] = "左边,剩余";dict["right"] = "右边";rens::um<string, string>::iterator it = dict.begin();while (it != dict.end()){cout << it->first << ":" << it->second << endl;++it;}cout << endl;
}

6.3 编写Unorderedset.h文件

基本逻辑思路是一样的,这里不在赘述,这里有一点注意的是,我们这里SetKeyOfT模板,可以不写,但是由于我们是将他与hstable文件以及unorderedmap.h文件一起编译的,为了照顾unorderedmap,我们这里加一下

参考代码:

#pragma once
#include"hstable.h"namespace rens
{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;using iterator = typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::Iterator;using const_iterator = typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::ConstIterator;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);}private:hash_bucket::HashTable<K, const K, SetKeyOfT, Hash> _ht;};void print(const unordered_set<int>& s){unordered_set<int>::const_iterator it = s.begin();while (it != s.end()){//*it = 1;cout << *it << " ";++it;}cout << endl;}void test_unordered_set(){unordered_set<int> us;us.insert(5);us.insert(1);us.insert(3);us.insert(5);us.insert(315);us.insert(5312);us.insert(333);for (auto e : us){cout << e << " ";}cout << endl;unordered_set<int>::iterator it = us.begin();while (it != us.end()){// *it = 1;cout << *it << " ";++it;}cout << endl;print(us);}
}

6.4 测试一下 

#include"unorderedset.h"
#include"unorderedmap.h"
int main()
{//test_unordered_map();rens::test_unordered_set();return 0;
}

到这里,我们对这两个容器的模拟实现就结束了,下一篇文章中我们将会讲解c++11的一些新的特性与相关知识!

http://www.dtcms.com/wzjs/155223.html

相关文章:

  • 中山建公司网站网站seo排名优化
  • wordpress 内存优化谷歌seo最好的公司
  • 陕西的建设厅官方网站网络服务商主要包括哪些
  • 广州市车管所网站建设优化大师手机版下载安装app
  • 成都网站建设公司 四川冠辰科技现代网络营销的方式
  • 物业公司网站建设方案下载百度2023最新版
  • 网站制作教程百度云seo81
  • 网站设计规范网站优化的方法有哪些
  • 如何选择镇江网站建设自助建站系统软件
  • 唐山建设工程造价信息网站人员优化方案怎么写
  • 垫江做网站百度人工在线客服
  • 互联网平台是做什么的seo是什么服务器
  • 哈尔滨优惠的网站建设2023年9月疫情又开始了吗
  • 怎么做彩票网站代理seo优化排名方法
  • 武汉市建设委员会网站中国十大seo公司
  • 大都会app官网下载贵港seo关键词整站优化
  • 网站收录下降的原因关键词优化排名软件推荐
  • 佛山免费自助建站模板抖音视频排名优化
  • 南京营销型网站建设关键词是什么
  • 驻马店做网站公司seo搜索引擎优化案例
  • 班级网站建设感想今日头条新闻10条
  • 十大中国网站制作网站案例
  • 寿光专业做网站的公司手机百度网页版
  • 网站设计 广西搜索网站大全排名
  • 哪些网站可以免费做推广seo软文是什么
  • 龙华网站建设的公司网页设计培训教程
  • 学做网站要学什么 做多久优化大师官网下载安装
  • 免费创建网站平台有哪些广州疫情最新新增
  • 如何做阿里巴巴的网站首页营销推广策划方案
  • app定制的价格开发网站优化公司哪个好