Set和Multisets

set和multiset会根据特定的排序准则,自动将元素排序。两者不同在于multisets允许元素重复而set不允许。

1.set和multiset的操作函数

生成、复制和销毁

set c              //产生一个空的set/multiset,其中不含任何元素
set c(op) //以op为排序准则,产生一个空的set/mulitset
set c1(c2) //产生某个set/multiset的副本,所有元素均被复制
set c(beg,end) //以区间[beg;end)内的元素产生一个set/multiset
set c(beg,end,op) //以op为排序准则,利用[beg;end]内的元素生成一个set/multiset
c.~set() //销毁所有元素,释放内存

其中set可为下列形式:

set<Elem>         //一个set,以less<>(operator<)为排序准则
set<Elem,op> //一个set,以op为排序准则
multiset<Elem> //一个multiset,以less<>(operator<)为排序准则
multiset<Elem,op> //一个multiset,以op为排序准则

特殊的搜寻函数

count(elem)       //返回“元素值为elem”的元素个数
find(elem) //返回"元素值为elem"的第一个元素的位置,如果找不到就返回end()
lower_bound(elem) //返回elem的第一个可安插位置,也就是“元素值>=elem”的第一个元素位置
upper_bound(elem) //返回elem的最后一个可安插位置,也就是“元素值>elem”的第一个元素位置
equal_range(elem) //返回elem可安插的第一个位置和最后一个位置,也就是“元素值==elem”的元素区间

下面是后面三个函数的一个例子

 #include <iostream>
#include <set>
using namespace std; int main()
{
set<int> c;
c.insert();
c.insert();
c.insert();
c.insert();
c.insert();
cout<<"lower_bound(3): "<<*c.lower_bound()<<endl;
cout<<"upper_bound(3): "<<*c.upper_bound()<<endl;
cout<<"equal_range(3): "<<*c.equal_range().first<<" "<<*c.equal_range().second<<endl;
cout<<endl;
cout<<"lower_bound(5): "<<*c.lower_bound()<<endl;
cout<<"upper_bound(5): "<<*c.upper_bound()<<endl;
cout<<"equal_range(5): "<<*c.equal_range().first<<" "<<*c.equal_range().second<<endl;
}

赋值

set和multiset只提供所有容器都提供的基本赋值操作

这些操作函数中,赋值操作的两端容器必须具有相容型别,而“比较准则”本身可以不同。如果准则不同,准则本身也会被赋值或交换

c1=c2        //将c2中所有元素赋值给c1
c1.swap(c2) //将c1和c2的元素交换
swap(c1,c2) //同上,此为全局函数

元素的安插和移除

c.insert(elem)      //安插一份elem副本,返回新元素位置
c.insert(pos,elem) //安插一份elem副本,返回新元素位置(pos只是个提示)
c.insert(beg,end) //将区间[beg;end)内所有元素的副本安插到c(无返回值)
c.erase(elem) //移除“与elem相等”的所有元素,返回被移除的元素个数
c.erase(pos) //移除迭代器pos锁指位置上的元素,无返回值
c.erase(beg,end) //移除区间[beg;end)内所有元素,无返回值
c.clear() //移除全部元素,将整个容器清空

因为set的元素不可以重复,因此安插动作可能会失败。为此set提供了如下接口来判断安插动作是否成功:

pair<iterator,bool> insert(const value_type& elem);

其中pair结构中second成员表示安插是否成功,first成员返回新元素的位置。

因为对迭代器操作而言,set和multiset所有元素都被视为常数,因此无法对其元素调用任何变动性算法。例如:remove()(因为remove()算法实际上是以一个参数值覆盖被移除的元素)。

如果要移除元素,只能使用它们所提供的成员函数。

2.set和multiset运用实例

 #include <iostream>
#include <set>
#include <iterator>
using namespace std; int main()
{
typedef set<int,greater<int> > IntSet;
IntSet coll1;
coll1.insert();
coll1.insert();
coll1.insert();
coll1.insert();
coll1.insert();
coll1.insert();
coll1.insert();
IntSet::iterator pos;
for(pos=coll1.begin();pos!=coll1.end();++pos)
cout<<*pos<<' ';
cout<<endl;
pair<IntSet::iterator,bool> status=coll1.insert();
if(status.second)
cout<<"4 inserted as element "<<distance(coll1.begin(),status.first)+<<endl;
else
cout<<"4 already exists"<<endl;
set<int> coll2(coll1.begin(),coll1.end());
copy(coll2.begin(),coll2.end(),ostream_iterator<int>(cout," "));
cout<<endl;
coll2.erase(coll2.begin(),coll2.find());
int num;
num=coll2.erase();
cout<<num<<" element(s) removed"<<endl;
copy(coll2.begin(),coll2.end(),ostream_iterator<int>(cout," "));
cout<<endl;
}

Map和Multimap

Map和Multimap将key/value当做元素,进行管理,他们可根据key的排序准则自动将元素排序。multimap允许重复元素(key值),maps不允许。

1.map和multimap的操作函数

生成、复制和销毁(跟set一样)

map c              //产生一个空的map/multimap,其中不含任何元素
map c(op) //以op为排序准则,产生一个空的map/mulitmap
map c1(c2) //产生某个map/multimap的副本,所有元素均被复制
map c(beg,end) //以区间[beg;end)内的元素产生一个map/multimap
map c(beg,end,op) //以op为排序准则,利用[beg;end)内的元素生成一个map/multimap
c.~map() //销毁所有元素,释放内存

其中,map可为下列形式:

map<key,Elem>          //一个map,以less<>(operator<)为排序准则
map<key,Elem,op> //一个map,以op为排序准则
multimap<key,Elem> //一个multimap,以less<>(operator<)为排序准则
multimap<key,Elem,op> //一个multimap,以op为排序准则

map和multimap也有类似于set和multiset的特殊搜寻操作函数

count(key)       //返回“键值为key”的元素个数
find(key) //返回"键值为key"的第一个元素的位置,如果找不到就返回end()
lower_bound(key) //返回"键值为key"的元素的第一个可安插位置,也就是“键值>=key”的第一个元素位置
upper_bound(key) //返回“键值为key”的元素的最后一个可安插位置,也就是“键值>key”的第一个元素位置
equal_range(key) //返回“键值为key”的元素可安插的第一个位置和最后一个位置,也就是“键值==key”的元素区间

与set和multiset一样,在map和multimap中(实际型别是pair<const key,T>),所有元素的key都被视为常数,因此不能对其调用任何变动性算法,也不能直接修改key(但是可以修改value)。

map和multimap的元素安插和移除函数跟set和multiset一样。不同的是map跟multimap安插和删除的是key/value值。

将map视为关联式数组

map提供下标操作符,支持元素的直接存取

m[key]  //返回一个reference,指向键值为key的元素。如果该元素尚未存在,就安插该元素

2.map和multimap的运用实例

 #include <iostream>
#include <map>
#include <string>
using namespace std; int main()
{
typedef map<string,float> StringFloatMap;
StringFloatMap stocks;
stocks["BASF"]=369.50;
stocks["VM"]=413.50;
stocks["Daimler"]=819.00;
stocks["BMW"]=834.00;
stocks["Siemens"]=842.20;
StringFloatMap::iterator pos;
for(pos=stocks.begin();pos!=stocks.end();++pos)
{
cout<<"stock: "<<pos->first<<"\t"
<<"price: "<<pos->second<<endl;
}
cout<<endl;
for(pos=stocks.begin();pos!=stocks.end();++pos)
pos->second*=;
for(pos=stocks.begin();pos!=stocks.end();++pos)
{
cout<<"stock: "<<pos->first<<"\t"
<<"price: "<<pos->second<<endl;
}
cout<<endl;
stocks["Volkswagen"]=stocks["VM"];
stocks.erase("VM");
for(pos=stocks.begin();pos!=stocks.end();++pos)
{
cout<<"stock: "<<pos->first<<"\t"
<<"price: "<<pos->second<<endl;
}
cout<<endl;
}

下面例子展示如何将multimap当做一个字典来使用

 #include <iostream>
#include <map>
#include <string>
#include <iomanip>
using namespace std; int main()
{
typedef multimap<string,string> StrStrMap;
StrStrMap dict;
dict.insert(make_pair("day","Tat"));
dict.insert(make_pair("strange","fremd"));
dict.insert(make_pair("car","Auto"));
dict.insert(make_pair("smart","elegant"));
dict.insert(make_pair("trait","Merkmak"));
dict.insert(make_pair("strange","seltsam"));
dict.insert(make_pair("smart","raffiniert"));
dict.insert(make_pair("smart","klug"));
dict.insert(make_pair("clever","raffiniert"));
StrStrMap::iterator pos;
cout.setf(ios::left,ios::adjustfield);
cout<<' '<<setw()<<"english "<<"german "<<endl;
cout<<setfill('-')<<setw()<<""<<setfill(' ')<<endl;
for(pos=dict.begin();pos!=dict.end();++pos)
{
cout<<' '<<setw()<<pos->first.c_str()
<<pos->second<<endl;
}
cout<<endl;
string word("smart");
cout<<word<<":"<<endl;
for(pos=dict.lower_bound(word);pos!=dict.upper_bound(word);++pos)
cout<<" "<<pos->second<<endl;
word=("raffiniert");
cout<<word<<":"<<endl;
for(pos=dict.begin();pos!=dict.end();++pos)
{
if(pos->second==word)
cout<<" "<<pos->first<<endl;
}
}

STL学习笔记(关联式容器)的更多相关文章

  1. STL学习笔记--关联式容器

    关联式容器依据特定的排序准则,自动为其元素排序.缺省情况下以operator<进行比较.set multiset map multimap是一种非线性的树结构,具体的说是采用一种比较高效的特殊平 ...

  2. 侯捷STL学习(九)--关联式容器(Rb_tree,set,map)

    layout: post title: 侯捷STL学习(九) date: 2017-07-21 tag: 侯捷STL --- 第十九节 容器rb_tree Red-Black tree是自平衡二叉搜索 ...

  3. STL学习笔记--序列式容器

    1.vector vector是一个线性顺序结构.相当于数组,但其大小可以不预先指定,并且自动扩展.故可以将vector看作动态数组. 在创建一个vector后,它会自动在内存中分配一块连续的内存空间 ...

  4. STL源码分析读书笔记--第5章--关联式容器

    1.关联式容器的概念 上一篇文章讲序列式容器,序列式容器的概念与关联式容器相对,不提供按序索引.它分为set和map两大类,这两大类各自有各自的衍生体multiset和multimap,的底层机制都是 ...

  5. C++ STL 学习笔记__(8)map和multimap容器

    10.2.9 Map和multimap容器 map/multimap的简介 ²  map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对.它提供基于key的快速检索能力. ² ...

  6. STL——关联式容器

    一.关联式容器 标准的STL关联式容器分为set(集合)/map(映射表)两大类,以及这两大类的衍生体multiset(多键集合)和 multimap(多键映射表).这些容器的底层机制均以RB-tre ...

  7. STL学习笔记--各种容器的运用时机

    如何选择最佳的容器类别? 缺省情况下应该使用vector.vector的内部结构简单,并允许随机存取,所以数据的存取十分方便灵活,数据的处理也够快. 如果经常要在序列的头部和尾部安插和移除元素,应采用 ...

  8. Effective STL 学习笔记 Item 30: 保证目标区间足够大

    Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...

  9. STL学习笔记

    简介 STL(Standard Template Library),即标准模版库,涵盖了常用的数据结构和算法,并具有跨平台的特点.STL是C++标准函数库的一部分,如下图所示: STL含有容器.算法和 ...

  10. 关联式容器(associative containers)

    关联式容器(associative containers) 根据数据在容器中的排列特性,容器可分为序列式(sequence)和关联式(associative)两种. 标准的STL关联式容器分为set( ...

随机推荐

  1. JS操作checkBox

    代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w ...

  2. Oracle clob 操作

    --Oracle clob 操作 -- Created on 2015/4/8 by TianPing declare -- Local variables here v_clob1 Clob; v_ ...

  3. 从jscript脚本混淆说起

    转载:http://www.freebuf.com/column/144897.html 脚本病毒是一个一直以来就存在,且长期活跃着的一种与PE病毒完全不同的一类病毒类型,其制作的门槛低.混淆加密方式 ...

  4. vboxmanage查询正在运行的vbox虚拟机

    系统:linux通用,virtualbox5.0 每次用下面命令启动vm虚拟机时,发现没办法知道它的IP. $ vboxmanage startvm <vmname> --type hea ...

  5. 【linux高级程序设计】(第十四章)TCP高级应用

    文件I/O方式比较 1.阻塞式文件I/O 进程从调用函数开始,直到返回这段时间都处于阻塞状态. 2.非阻塞式文件I/O 如果当前没有数据可操作,将不阻塞当前进程,而是立即返回一个错误信息.需要反复尝试 ...

  6. C# Socket的粘包处理(转)

    http://www.cnblogs.com/aarond/p/Socket111.html 当socket接收到数据后,会根据buffer的大小一点一点的接收数据,比如: 对方发来了1M的数据量过来 ...

  7. linux文件名匹配

    *   匹配文件名中的任何字符串,包括空字符串. ? 匹配文件名中的任何单个字符. [...]   匹配[ ]中所包含的任何字符. [!...]   匹配[ ]中非感叹号!之后的字符. 如: s*   ...

  8. (22)C#windows打包部署

    程序做好后需要打包部署后才能使用 一.创建安装项目 解决方案右键-添加-新建项目-其他项目类型-安装和部署-双击进入文件系统. 二.制作安装程序 一个完整的安装程序包括项目输出文件.内容文件.桌面快捷 ...

  9. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分)(线段树单点修改)

    [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14968  Solved: 6079[Submit][Stat ...

  10. Xamarin XAML语言教程通过数据绑定使用Progress属性

    Xamarin XAML语言教程通过数据绑定使用Progress属性 开发者除了可以为ProgressBar定义的Progress属性直接赋双精度类型的值外,还可以通过数据绑定的方式为该属性赋值,此时 ...