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

广西论坛网站建设郑州网络推广哪家口碑好

广西论坛网站建设,郑州网络推广哪家口碑好,昆山建设招投标网站,wordpress怎么编辑模板1 序列式容器和关联式容器 前⾯我们已经接触过STL中的部分容器如:string、vector、list、deque、array、forward_list等,这 些容器统称为序列式容器,因为逻辑结构为线性序列的数据结构,两个位置存储的值之间⼀般没有紧 密的关联关…

1 序列式容器和关联式容器

前⾯我们已经接触过STL中的部分容器如:string、vector、list、deque、array、forward_list等,这 些容器统称为序列式容器,因为逻辑结构为线性序列的数据结构,两个位置存储的值之间⼀般没有紧 密的关联关系,⽐如交换⼀下,他依旧是序列式容器。顺序容器中的元素是按他们在容器中的存储位 置来顺序保存和访问的。

关联式容器也是⽤来存储数据的,与序列式容器不同的是,关联式容器逻辑结构通常是⾮线性结构, 两个位置有紧密的关联关系,交换⼀下,他的存储结构就被破坏了。顺序容器中的元素是按关键字来 保存和访问的。关联式容器有map/set系列和unordered_map/unordered_set系列。

本届我要讲解的是map/set,他的底层是用红黑树,红黑树的本质又是一颗平衡二叉树,set是key搜索场景结果,map是key/value搜索场景结构。

2  set系列的使用

 2.1 set和multiset文档

如果你想要了解全部关于set的用法,你可以按照这个网站进行参考。

<set> - C++ Reference

2.2 set的介绍

• set的声明如下,T就是set底层关键字的类型。

• set默认要求T⽀持⼩于⽐较,如果不⽀持或者想按⾃⼰的需求⾛可以⾃⾏实现仿函数传给第⼆个模版参数

• set底层存储数据的内存是从空间配置器申请的,如果需要可以⾃⼰实现内存池,传给第三个参 数。

• ⼀般情况下,我们都不需要传后两个模版参数。

• set底层是⽤红⿊树实现,增删查效率是O(logN) ,迭代器遍历是⾛的搜索树的中序,所以是有序的。

• 前⾯部分我们已经学习了vector/list等容器的使⽤,STL容器接⼝设计,⾼度相似,所以这⾥我们 就不再⼀个接⼝⼀个接⼝的介绍,⽽是直接带着⼤家看⽂档,挑⽐较重要的接⼝进⾏介绍。

2.3 set的构造和迭代器

set的构造我们关注以下⼏个接⼝即可。

set的⽀持正向和反向迭代遍历,遍历默认按升序顺序,因为底层是⼆叉搜索树,迭代器遍历⾛的中 序;⽀持迭代器就意味着⽀持范围for,set的iterator和const_iterator都不⽀持迭代器修改数据,修改 关键字数据,破坏了底层搜索树的结构。

// empty (1) ⽆参默认构造
explicit set(const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());// range (2) 迭代器区间构造
template <class InputIterator>
set(InputIterator first, InputIterator last,const key_compare& comp = key_compare(),const allocator_type & = allocator_type());
// copy (3) 拷⻉构造
set(const set& x);// initializer list (5) initializer 列表构造
set(initializer_list<value_type> il,const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());// 迭代器是⼀个双向迭代器
iterator->a bidirectional iterator to const value_type// 正向迭代器
iterator begin();
iterator end();// 反向迭代器
reverse_iterator rbegin();
reverse_iterator rend();

2.4 set的增删查

set的增删查关注下面几个就行了:

Member types
key_type->The first template parameter(T)
value_type->The first template parameter(T)// 单个数据插⼊,如果已经存在则插⼊失败
pair<iterator, bool> insert(const value_type& val);//列表插⼊,已经在容器中存在的值不会插⼊
void insert(initializer_list<value_type> il);// 迭代器区间插⼊,已经在容器中存在的值不会插⼊
template <class InputIterator>
void insert(InputIterator first, InputIterator last);// 查找val,返回val所在的迭代器,没有找到返回end()
iterator find(const value_type& val);// 查找val,返回Val的个数
size_type count(const value_type& val) const;
// 删除⼀个迭代器位置的值iterator  erase(const_iterator position);
// 删除val,val不存在返回0,存在返回1size_type erase(const value_type & val);
// 删除⼀段迭代器区间的值
iterator  erase(const_iterator first, const_iterator last);// 返回⼤于等val位置的迭代器
iterator lower_bound(const value_type& val) const;// 返回⼤于val位置的迭代器
iterator upper_bound(const value_type& val) const;

2.5 对于insert和迭代器遍历使用:

#include<set>
int main()
{// 去重+升序排序set<int> s = {5,6,17,12,4,8,5};//set<int, greater<int>> s;s.insert(5);s.insert(2);s.insert(7);s.insert(5);//set<int>::iterator it = s.begin();auto it = s.begin();while (it != s.end()){// error C3892: “it”: 不能给常量赋值//*it = 1;cout << *it << " ";++it;}cout << endl;// 插入一段initializer_list列表值,已经存在的值插入失败s.insert({ 2,8,3,9 });for (auto e : s){cout << e << " ";}cout << endl;set<string> strset = { "sort", "insert", "add" };// 遍历string比较ascll码大小顺序遍历的for (auto& e : strset){cout << e << " ";}cout << endl;// O(N)auto it1 = find(s.begin(), s.end(), 3);// O(logN)auto it2 = s.find(3);return 0;
}

2.6 find和erase的使用

{set<int> s = { 4,2,7,2,8,5,9 };for (auto e : s){cout << e << " ";}cout << endl;s.erase(s.begin());for (auto& e : s){cout << e << " ";}cout << endl;//直接删除x/*int x;cin >> x;int num = s.erase(x);if (num == 0){cout << "不存在!" << endl;}for (auto e : s){cout << e << " ";}cout << endl;*/int x = 0;cin >> x;if (s.count(x)){cout << "在" << endl;}else{cout << "不在" << endl;}return 0;}

2.7 multiset和set的差异

multiset和set的使⽤基本完全类似,主要区别点在于multiset⽀持值冗余,那么 insert/find/count/erase都围绕着⽀持值冗余有所差异,具体参看下⾯的样例代码理解。

int main()
{multiset<int> s = { 4,2,7,2,4,8,4,5,4,9 };auto it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;//相比set不同的是,x可能会存在多个,find查找中序的第一个int x;cin >> x;auto pos = s.find(x);while (pos != s.end() && *pos == x){cout << *pos << " ";++pos;}cout << endl;//相比set不同的是,count会返回x的实际个数cout << s.count(x) << endl;//相比set不同的是,erase给值时会删除所有的xs.erase(x);for (auto e : s){cout << e << " ";}cout << endl;return 0;
}

 3 map系列的使用

3.1 map的介绍

map的声明如下,Key就是map底层关键字的类型,T是map底层value的类型,set默认要求Key⽀持 ⼩于⽐较,如果不⽀持或者需要的话可以⾃⾏实现仿函数传给第⼆个模版参数,map底层存储数据的 内存是从空间配置器申请的。⼀般情况下,我们都不需要传后两个模版参数。map底层是⽤红⿊树实 现,增删查改效率是 O(logN) ,迭代器遍历是⾛的中序,所以是按key有序顺序遍历的。

3.2 pair的介绍

map底层的红⿊树节点中的数据,使⽤pair存储键值对数据。

typedef pair<const Key, T> value_type;
template <class T1, class T2>
struct pair 
{typedef T1 first_type;typedef T2 second_type;T1 first;T2 second;pair(): first(T1()), second(T2()){}pair(const T1& a, const T2& b): first(a), second(b){}template<class U, class V> 
pair (const pair<U,V>& pr): first(pr.first), second(pr.second){}};
template <class T1,class T2>inline pair<T1,T2> make_pair (T1 x, T2 y)
{return ( pair<T1,T2>(x,y) );
}

3.3 map的构造

map的构造我们关注以下⼏个接⼝即可。

map的⽀持正向和反向迭代遍历,遍历默认按key的升序顺序,因为底层是⼆叉搜索树,迭代器遍历⾛ 的中序;⽀持迭代器就意味着⽀持范围for,map⽀持修改value数据,不⽀持修改key数据,修改关键字数据,破坏了底层搜索树的结构。

// empty (1) ⽆参默认构造
explicit map(const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());// range (2) 迭代器区间构造
template <class InputIterator>
map(InputIterator first, InputIterator last,const key_compare& comp = key_compare(),const allocator_type & = allocator_type());// copy (3) 拷⻉构造
map(const map& x);// initializer list (5) initializer 列表构造
map(initializer_list<value_type> il,const key_compare & comp = key_compare(),const allocator_type & alloc = allocator_type());// 迭代器是⼀个双向迭代器
iterator->a bidirectional iterator to const value_type// 正向迭代器
iterator begin();
iterator end();// 反向迭代器
reverse_iterator rbegin();
reverse_iterator rend();

3.4 map的增删查

map的增删查关注以下⼏个接⼝即可:

map增接⼝,插⼊的pair键值对数据,跟set所有不同,但是查和删的接⼝只⽤关键字key跟set是完全 类似的,不过find返回iterator,不仅仅可以确认key在不在,还找到key映射的value,同时通过迭代 还可以修改value

Member types
key_type->The first template parameter(Key)
mapped_type->The second template parameter(T)
value_type->pair<const key_type, mapped_type>// 单个数据插⼊,如果已经key存在则插⼊失败, key存在相等value不相等也会插⼊失败
pair<iterator, bool> insert(const value_type& val);// 列表插⼊,已经在容器中存在的值不会插⼊
void insert(initializer_list<value_type> il);// 迭代器区间插⼊,已经在容器中存在的值不会插⼊
template <class InputIterator>
void insert(InputIterator first, InputIterator last);// 查找k,返回k所在的迭代器,没有找到返回end()
iterator find(const key_type& k);// 查找k,返回k的个数
size_type count(const key_type& k) const;// 删除⼀个迭代器位置的值
iterator  erase(const_iterator position);// 删除k,k存在返回0,存在返回1size_type erase(const key_type & k);
// 删除⼀段迭代器区间的值
iterator  erase(const_iterator first, const_iterator last);// 返回⼤于等k位置的迭代器
iterator lower_bound(const key_type & k);// 返回⼤于k位置的迭代器
const_iterator lower_bound(const key_type& k) const;

前⾯提到map⽀持修改mapped_type数据,不⽀持修改key数据,修改关键字数据,破坏了底层搜 索树的结构。

map第⼀个⽀持修改的⽅式时通过迭代器,迭代器遍历时或者find返回key所在的iterator修改,map 还有⼀个⾮常重要的修改接⼝operator[],但是operator[]不仅仅⽀持修改,还⽀持插⼊数据和查找数据,所以他是⼀个多功能复合接口

需要注意从内部实现⻆度,map这⾥把我们传统说的value值,给的是T类型,typedef为 mapped_type。⽽value_type是红⿊树结点中存储的pair键值对值。⽇常使⽤还是习惯将这⾥的 T映射值叫做value。

3.5 构造遍历和增删查的使用

#include<map>int main()
{map<string, string> dict;// C++98pair<string, string> kv1("sort", "排序");dict.insert(kv1);dict.insert(pair<string, string>("string", "字符串"));dict.insert(make_pair("pair", "一对"));// C++11dict.insert({ "left", "左边" });/*map<string, string>::iterator it = dict.begin();*///map<string, string>::iterator it = dict.begin();auto it = dict.begin();while (it != dict.end()){//cout << (*it).first <<" "<< (*it).second << endl;cout << it->first << " " << it->second << endl;/*cout << it.operator->()->first << " " << it.operator->()->second << endl;*/++it;}cout << endl;//initializer_list构造及迭代遍历map<string,string> dict1 = { {"left", "左边"}, {"left", "xxxx"}, {"right", "右边"},{"insert", "插入"},{ "string", "字符串" } };dict1.insert({ "left","121431141" });for (const auto& kv : dict1){cout << kv.first << " " << kv.second << endl;}return 0;
}

3.6map迭代器和[]的使用

int main()
{string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉" };/*map<string, int> countMap;*///for (auto& e : arr)//{//	/*auto it = countMap.find(e);//	if (it == countMap.end())//	{//		countMap.insert({ e, 1 });//	}//	else//	{//		it->second++;//	}*///	countMap[e]++;//}map<string, int> countMap;for (auto& e : arr){countMap[e]++;}pair<map<string, int>::iterator, bool> ret1 = countMap.insert({ "草莓", 1 });pair<map<string, int>::iterator, bool> ret2 = countMap.insert({ "西瓜", 1 });for (const auto& kv : countMap){cout << kv.first <<" "<< kv.second << endl;}map<string, string> dict;// 插入(基本不会这样用)dict["left"];// 插入+修改dict["right"] = "右边";// 修改dict["left"] = "左边";// 查找cout << dict["left"] << endl;return 0;
}

3.7multimap和map的差异

multimap和map的使⽤基本完全类似,主要区别点在于multimap⽀持关键值key冗余,那么 insert/find/count/erase都围绕着⽀持关键值key冗余有所差异,这⾥跟set和multiset完全⼀样,⽐如find时,有多个key,返回中序第⼀个。其次就是multimap不⽀持[],因为⽀持key冗余,[]就只能⽀ 持插⼊了,不能⽀持修改。

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

相关文章:

  • 网站外包费用怎么做分录抖音关键词优化
  • 企业网站建立庆云县有几家百度seo招聘
  • 眉县住房和建设委员会网站百度推广助手
  • 做纪录片卖给视频网站百度app手机版
  • 英文网站建设运营百度搜索结果优化
  • 中国网库是做什么的seo推广策划
  • 做游戏网站年入百万百度地图关键词排名优化
  • 做旅游网站的关注与回复网站开发流程有哪几个阶段
  • 镇江网站建设远航科技信息流推广方式
  • 一级做爰片a视频网站试看广告关键词有哪些
  • 专做投放广告网站短期职业技能培训班
  • 高质量的中山网站建设今日新闻事件
  • 做网站客户拖着不验收西安网络推广公司网络推广
  • 用什么建网站 cms企业网站优化方案案例
  • 做瞹瞹网站深圳seo优化公司排名
  • 建设网站建站公司域名备案官网
  • wps演示做的和网站导航可以发外链的网站整理
  • php网站开发过程百度一下就知道官方网站
  • 免费信息网站排名广告留电话号的网站
  • wordpress电脑主题包头seo
  • 软件园学生班级优化大师
  • 网上商城开发费用南宁百度seo推广
  • 程序员做网站美工能过关吗关键字排名优化工具
  • 长春880元网站建设今日国内新闻
  • 网站建设购买什么境外主机宁德市疫情最新消息
  • 上海做网站 公司 哪家好个人免费建站系统
  • 中企动力做网站什么叫关键词举例
  • 好的网站优化公司搜索引擎优化技术有哪些
  • 网站后台的验证码蚂蚁链接bt链接
  • 交易网站域名网络服务是什么