STL总结之set/multiset和map/multimap

/******************************************************set和Multiset****************************************************/

使用set和multiset之前,必须先含入头文件: #include

namespace std{

template,class Allocator = allocator>

class set;

template,class Allocator = allocator>

class multiset;

}

关于排序准则:

1)必须是反对称的:若x

2)必须是可传递的:若x

3)必须是非自反的:x

set和multiset通常由平衡二叉树实现.

自动排序造成set和multiset的一个重要限制:你不能直接改变元素值这样会打乱原本的排序顺序。为此,要改变元素值,

必须先删除旧元素,再插入新元素。

通过迭代器进行元素间接存取,有一个限制:从迭代器角度看,元素值是常数。

set 和 multiset的构造析构函数:

set c;

set c(op);

set c1(c2);

set c(beg,end);

set c(beg,end,op);

c.~set()

set可为以下形式:

set/multiset

set/multiset

有两种方式可以定义排序准则(后有例子):

1)以template参数定义:

std::set> coll;  这种情况下,排序准则就是型别的一部分,只有排序准则相同的容器才能被合并

2)以构造函数参数定义:

typedef setRuntimeCmp> IntSet; 

RuntimeCmp reverse_order(RuntimeCmp::reverse);

IntSet coll2(reverse_order);

如果执行期才获得排序准则,且需要用到不同的排序准则(但数据型别必须相同),此方式可派上用场。

元素比较动作只能用于型别相同的容器,换言之,元素和排序准则都必须有相同的型别,否则编译出错。如果要比较拥有不同排序准则的容器,必须采用比较算法。

c.size() c.empty() c.max_size() == != < > <=  >=

set和multiset的搜寻操作函数:

count(elem)

find(elem) // 找第一个,找不到就返回end()

lower_bound(elem)

upper_bound(elem)

equal_range(elem)

赋值操作的两端容器必须具有相同型别。“比较准则”本身可以不同,但其型别必须相同,如果准则不同,准则本身也会被赋值/交换

c1 = c2;   c1.swap(c2);   swap(c1,c2);  

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

c.insert(elem)   // 返回新元素位置

c.insert(pos,elem)  //返回新元素位置

c.insert(beg,end)  //void

c.erase(elem)  //返回被移除的元素个数

c.erase(pos)   //void ,vector返回的是下一个元素位置,这种差别完全是为了性能

c.erase(beg,end)   // void

c.clear()

//无 remove

multiset允许元素重复,而set不允许。因此将某元素安插至一个set内,而该set已含同值元素,则安插失败,所以set的返回型别

是以pair组织起来的两个值:pair,first 返回新元素的位置,second表示是否安插成功

set和multiset运用实例:

#include

#include

#include

#include

using namespace std;

int main(){

typedef set> IntSet;

IntSet coll1;

coll1.insert(4);

coll1.insert(3);

coll1.insert(5);

coll1.insert(1);

coll1.insert(6);

coll1.insert(2);

coll1.insert(5); // 会被程序忽略

IntSet::iterator pos;

for(pos = coll1.begin();pos != coll1.end; ++pos){

cout<<*pos<" ";

}

cout<

pair status = coll1.insert(4);

if(status.second){

cout<<"4 inserted as element "

<

<

}else{

cout<<"4 already exists"<

}

set coll2(coll1.begin(),coll1.end());

copy(coll2.begin(),coll2.end(),ostream_iterator(cout," "));

cout<

coll2.erase(coll2.begin(),coll2.find(3));

int num;

num = coll2.erase(5);

cout<

copy(coll2.begin(),coll2.end(),ostream_iterator(cout," "));

cout<

}

执行期指定排序准则:

#include

#include

#include "print.hpp"

using namespace std;

template

class RuntimeCmp{

public:

enum cmp_mode{normal,reverse};

private:

cmp_mode mode;

public:

RuntimeCmp(cmp_mode m=normal) : mode(m) {

}

bool operator()(const T& t1,const T& t2) const{

return mode = normal ? t1 < t2 : t2 < t1;

}

bool operator == (const RuntimeCmp& rc){

return  mode == rc.mode;

}

};

typedef set> IntSet;

void fill(IntSet& set);

int main(){

IntSet coll1;

fill(coll1);

PRINT_ELEMENTS(coll1,"coll1: ");

RuntimeCmp reverse_order(RuntimeCmp::reverse);

IntSet coll2(reverse_order);

fill(coll2);

PRINT_ELEMENTS(coll2,"coll2: ");

coll1 = coll2;

coll1.insert(3);

PRINT_ELEMENTS(coll1,"coll1: ");

}

void fill(IntSet& set){

set.insert(4);

set.insert(7);

set.insert(5);

set.insert(1);

set.insert(6);

set.insert(2);

set.insert(5);

}

/******************************************************map和multimap****************************************************/

使用map和multimap之前,必须包含头文件: #include

namespace std{

template

class Compare = less,

class Allocator = allocator>>

class map;

template

class Compare = less,

class Allocator = allocator>>

class multimap;

}

key/value 必须具备可复制,可赋值性质;对排序准则而言,key必须是可比较的。map可作为关联式数组使用。

不可以直接更改元素的key,当value是非常数时,value可更改。若一定要改变元素的key,只有一条路:以一个value相同的

新元素替换掉旧元素。map提供了一种非常方便的手法让你改变元素的key:

coll["new_key"] = coll["old_key"]; 

coll.erase("old_key");

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

std::cout<

map/multimap绝大多数操作都与set/multiset相同,此处略过。

成员函数find用来查找拥有某个key值的第一个元素,并返回一个指向该位置的迭代器或end()。你不能用find来查找拥有某特定

value的元素,你必须用find_if,或干脆写一个显式循环:

std::multimap coll;

......

std::multimap::iterator pos;

for(pos = coll.begin();pos != coll.end(); ++pos){

if(pos->second == value){

do_something();

}

}

有三种不同方法可以将value传入map:

1)运用value_type:value_type是容器本身提供的型别定义。

std::map coll;

coll.insert(std::map::value_type("otto",22.3));

2)运用pair<>

coll.insert(std::pair("otto",22.3)); 

coll.insert(std::pair("otto",22.3));

第一个型别并不正确,但会被转换成真正的元素型别,因为insert成员函数被定义为member template

3)运用make_pair():最简单,这个函数根据传入的参数构造一个pair对象

coll.insert(std::make_pair("otto",22.3)); // member template insert()  执行必要的型别转换

eg: std::map coll;

if(coll.insert(std::make_pair("otto",22.3)).second){  //对于insert(value),返回pair

std::cout<<"ok can insert"<

}else{

std::cout<<"Oops,could not insert,key already exists"<

}

如果multimap内含重复元素,你不能使用erase()来删除重复元素中的第一个,你可以用成员函数find:

typedef std::multimap StringFloatMMap;

StringFloatMMap coll;

StringFloatMMap::iterator pos;

pos = coll.find(key);

if(pos != coll.end()){

coll.erase(pos);

}

移除迭代器所指对象时,有一个很大的危险:

for(pos = coll.begin();pos != coll.end(); ++pos){

if(pos->second == value){

coll.erase(pos); // Error!

}

对pos所指元素实施erase(),会使pos不再成为一个有效的coll迭代器,此后未对pos重新设值就径行使用pos,前途未卜!

应该这样:

for(pos = coll.begin();pos != coll.end(); ){

if(pos->second == value){

coll.erase(pos++);

}else{

++pos;

}

}

map和multimap运用实例:

将map当做关联式数组:

#include

#include

#include

using namespace std;

int main(){

typedef map StringFloatMap;

StringFloatMap stocks;

stocks["BASF"] = 369.50;

stocks["VW"] = 413.50;

stocks["Daimler"] = 819.00;

stocks["BWM"] = 822.00;

stocks["Siements"] = 834.20;

StringFloatMap::iterator pos;

for(pos = stocks.begin(); pos != stocks.end(); ++pos){

cout<<"stock: "<first<<"\t"

<<"price: "<second<

}

cout<

for(pos = stocks.begin(); pos != stocks.end(); ++pos){

pos->second *=2;

}

for(pos = stocks.begin(); pos != stocks.end(); ++pos){

cout<<"stock: "<first<<"\t"

<<"price: "<second<

}

cout<

stocks["Volkswagen"] = stocks["VM"];

stocks.erase["VM"];

for(pos = stocks.begin(); pos != stocks.end(); ++pos){


cout<<"stock: "<first<<"\t"

<<"price: "<second<

}

}

将multimap当做字典:

#include

#include

#include

#include

using namespace std;

int main(){

typedef multimap StrStrMMap;

StrStrMMap dict;

dict.insert(make_pair("day","Tag"));

dict.insert(make_pair("strange","fremd"));

dict.insert(make_pair("car","Auto"));

dict.insert(make_pair("smart","elegant"));

dict.insert(make_pair("trait","Merkmal"));

dict.insert(make_pair("strance","seltsam"));

dict.insert(make_pair("smart","raffiniert"));

dict.insert(make_pair("smart","klug"));

dict.insert(make_pair("clever","raffiniert"));

StrStrMMap::iterator pos;

cout.setf(ios::left,ios::adjustfield);

cout<<' '<

cout<

for(pos = dict.begin(); pos != dict.end(); ++pos){

cout<<' '<first.c_str()

<second<

}

cout<

string world("smart");

cout<

for(pos = dict.lower_bound(word); pos != dict.upper_bound(word); ++pos){

cout<<" "<second<

}

word = ("raffiniert");

for(pos = dict.begin(); pos != dict.end(); ++pos){

if(pos->second ==word){

cout<<"  "<first<

}

}

}

用find_if算法搜寻具有某特定值的元素:

#include

#include

#include

using namespace std;

template

class value_equals{

private:

V value;

public:

value_equals(const V& v) : value(v){ }

bool operator()(pairelem){

return elem.second == value;

}

};

int main(){

typedef map FloatFloatMap;

FloatFloatMap coll;

FloatFloatMap::iterator pos;

coll[1] = 7;

coll[2] = 4;

coll[3] = 6;

coll[4] = 3;

coll[5] = 2;

coll[6] = 1;

coll[7] = 3;

pos = coll.find(3.0);

if(pos != coll.end()){

cout<first<<": "

<second<

}

pos = find_if(coll.begin(),coll.end(),value_equals(3.0));

if(pos != coll.end()){

cout<first<<": "

<second<

}

}

综合实例:运用map,multimap并于执行期指定排序准则

#include

#include

#incldue

#include

#include

using namespace std;

class RuntimeStringCmp{

public:

enum cmp_mode{normal,nocase};

private:

const cmp_mode mode;

static bool nocase_compare(char c1,char c2){

return toupper(c1)

}

public:

RuntimeStringCmp(cmp_mode m = normal) : mode(m){ }

bool operator()(const string& s1,const string& s2) const {

if(mode == normal){

return s1 < s2 ;

}else{

return lexicographical_compare(s1.begin(),s1.end(),s2.begin(),s2.end(),nocase_compare);

}

}

};

typedef map StringStringMap;

void fillAndPrint(StringStringMap& coll);

int main(){

StringStringMap coll1;

fillAndPrint(coll1);

StringStringMap ignorecase(StringStringMap::nocase);

StringStringMap coll2(ignorecase);

fillAndPrint(coll2);

}

void fillAndPrint(StringStringMap& coll){

coll["deutsch"] = "German";

......

StringStringMap::iterator pos;

cout.setf(ios::left,ios::adjustfield);

for(pos = coll.begin(); pos != coll.end(); ++pos){

cout<first.c_str()<<" "

<second<

}

cout<

}





你可能感兴趣的:(STL/Boost,STL,set,multiset,map,multimap)