C++ STL一一map和multimap

来源:互联网 发布:php任意文件上传代码 编辑:程序博客网 时间:2024/05/19 12:39

一、特点

1.采用键值对<key,value>做元素,可根据key的排序准则进行排序

2.multimap允许元素重复,map不允许

3.不可以直接改变元素的key,因为这会破坏正确次序,要修改key,可以先移除该key的元素,再添加该key的元素,从迭代器的观点来看,key是常数。value可以直接修改,前提是value并非常数型态

二、构造和析构

map c //产生一个空的map/multimap,其中不含任何元素  map c(op) //以op为排序准则,产生一个空的map/multimap  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/multimap可以为下列形式

map<Key,Elem> //一个map,以less<>(operator<)为准则排序  map<Key,Elem,op> //一个map,以op为准则排序  multimap<Key,Elem> //一个multimap,以less<>(operator<)为准则排序  multimap<Key,Elem,op> //一个multimap,以op为准则排序 
两种定义排序准则的方式

1.以template参数定义

例如:

std::map<float,std::string,std::greater<float>> coll;
排序准则是型别的一部分,确保“只有排序准则相同的容器”才能合并。

2.以构造函数参数定义

同一个型别可以运用不同的排序准则,而排序准则的初始值或状态也可以不同。如果执行期才获得排序准则,并且需要用到不同的排序准则(但数据型别必须相同)

三、非变动性操作

c.size()   //返回当前元素数量    c.empty()  //判断大小是否为0    c.max_size() //返回可容纳的元素最大数量    
外加比较性动作

四、特殊的搜寻动作

count(key) //返回"键值等于key"的元素个数  find(key) //返回“键值等于key”的第一个元素,如果找不到就返回end()  lower_bound(key) //返回“键值为key”的第一个可安插位置,也就是“键值>=key”的第一个元素位置  upper_bound(key) //返回“键值为key”的最后一个可安插位置,也就是“键值>key”的第一个元素位置  equal_range(key) //返回“键值为key”的元素的第一个可安插位置和最后一个可安插位置,也就是“键值==key”的元素区间 
五、赋值
c1 = c2  //将c2的元素全部赋值给c1     c1.swap(c2);    swap(c1,c2);    
六、迭代器
c.begin() //返回一个双向迭代器(key被视为常数),指向第一个元素    c.end()   //返回一个双向迭代器(key被视为常数),指向最后元素的下一位置    c.rbegin() //返回一个逆向迭代器,指向逆向迭代的第一个元素    c.rend()    //返回一个逆向迭代器,指向逆向迭代的最后元素的下一位置   
七、安插和删除
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() //移除全部元素,将整个容器清空  
安插一个key/value pair时,在map和multimap内部,key被视作为常数。那么要么提供正确型别,要么提供显示/隐式转换,有三个不同的方法可以将value传入map

1.运用value_type

为了避免隐式转换,可以利用value_type来明确传递正确的型别

std::map<std::string,float> coll;coll.insert(std::map<std::string,float>::value_type("otto",22.3));
2.运用pair<>

std::map<std::string,float> coll;coll.insert(std::pair<const std::string,float>("otto",22.3));
3.运用make_pair()

这个是最常用,也是最方便的方法

std::map<std::string,float> coll;coll.insert(std::make_pair("otto",22.3));

如果要移除“拥有某个value”的元素,调用erase()即可

std::map<std::string,float> coll;coll.erase(key);
但是针对multimap,需要删除重复元素中的第一个,需要处理:

typedef std::multimap<std::string,float> StringFloatMMap;StringFloatMMap coll;StringFloatMMap::iterator pos;pos = coll.find(key);if(pos != coll.end()){   coll.erase(pos);}
上述讲述的是移除key值所对应的某个元素,但是当你需要直接移除value所对应的元素时,需要进行如下处理,因为对pos所指元素实施erase(),会使pos不再成为一个有效的coll迭代器,如果此后你未对pos进行赋值就直接使用,前途未卜,事实上,只要一个++pos就会导致这种未定义的行为。

但是如果erase()总是返回下一元素的位置,就可以了,下面是移除“迭代器所指元素”的正确做法:

typedef std::map<std::string,float> StringFloatMap;StringFloatMap coll;StringFloatMap::iterator pos;//remove all elements having a certain valuefor(pos = coll.begin();pos!=coll.end();){   if(pos->second == value)coll.erase(pos++);else++pos;}
这样,pos++会将pos移向下一元素,但返回其原始值(所指原位置)的一个副本。因此,当erase()被调用,pos已经不再指向那个即将被移除的元素了。

八、将map视为关联式数组

通常,关联式容器不提供元素的直接存取,必须依靠迭代器,但是map例外,它提供下标操作,支持元素的直接存取。

不过,索引的下标值为key值

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

九、运行实例

#include <iostream>#include <map>#include <string>using namespace std;int main(){    /* create map / associative array     * - keys are strings     * - values are floats     */    typedef map<string,float> StringFloatMap;    StringFloatMap stocks;      // create empty container    // insert some elements    stocks["BASF"] = 369.50;    stocks["VW"] = 413.50;    stocks["Daimler"] = 819.00;    stocks["BMW"] = 834.00;    stocks["Siemens"] = 842.20;    // print all elements    StringFloatMap::iterator pos;    for (pos = stocks.begin(); pos != stocks.end(); ++pos) {        cout << "stock: " << pos->first << "\t"             << "price: " << pos->second << endl;    }    cout << endl;    // boom (all prices doubled)    for (pos = stocks.begin(); pos != stocks.end(); ++pos) {        pos->second *= 2;    }    // print all elements    for (pos = stocks.begin(); pos != stocks.end(); ++pos) {        cout << "stock: " << pos->first << "\t"             << "price: " << pos->second << endl;    }    cout << endl;    /* rename key from "VW" to "Volkswagen"     * - only provided by exchanging element     */    stocks["Volkswagen"] = stocks["VW"];    stocks.erase("VW");    // print all elements    for (pos = stocks.begin(); pos != stocks.end(); ++pos) {        cout << "stock: " << pos->first << "\t"             << "price: " << pos->second << endl;    }}
运行结果

stock: BASF     price: 369.5stock: BMW      price: 834stock: Daimler  price: 819stock: Siemens  price: 842.2stock: VW       price: 413.5stock: BASF     price: 739stock: BMW      price: 1668stock: Daimler  price: 1638stock: Siemens  price: 1684.4stock: VW       price: 827stock: BASF     price: 739stock: BMW      price: 1668stock: Daimler  price: 1638stock: Siemens  price: 1684.4stock: Volkswagen       price: 827请按任意键继续. . .

将multimap当做字典

#include <iostream>#include <map>#include <string>#include <iomanip>using namespace std;int main(){    // define multimap type as string/string dictionary    typedef multimap<string,string> StrStrMMap;    // create empty dictionary    StrStrMMap dict;    // insert some elements in random order    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("strange","seltsam"));    dict.insert(make_pair("smart","raffiniert"));    dict.insert(make_pair("smart","klug"));    dict.insert(make_pair("clever","raffiniert"));    // print all elements    StrStrMMap::iterator pos;    cout.setf (ios::left, ios::adjustfield);    cout << ' ' << setw(10) << "english "         << "german " << endl;    cout << setfill('-') << setw(20) << ""         << setfill(' ') << endl;    for (pos = dict.begin(); pos != dict.end(); ++pos) {        cout << ' ' << setw(10) << pos->first.c_str()             << pos->second << endl;    }    cout << endl;    // print all values for key "smart"    string word("smart");    cout << word << ": " << endl;    for (pos = dict.lower_bound(word);         pos != dict.upper_bound(word); ++pos) {            cout << "    " << pos->second << endl;    }    // print all keys for value "raffiniert"    word = ("raffiniert");    cout << word << ": " << endl;    for (pos = dict.begin(); pos != dict.end(); ++pos) {        if (pos->second == word) {            cout << "    " << pos->first << endl;        }    }}
运行结果:

 english   german-------------------- car       Auto clever    raffiniert day       Tag smart     elegant smart     raffiniert smart     klug strange   fremd strange   seltsam trait     Merkmalsmart:    elegant    raffiniert    klugraffiniert:    clever    smart请按任意键继续. . .
搜寻具有特定实值的元素

#include <iostream>#include <algorithm>#include <map>using namespace std;/* function object to check the value of a map element */template <class K, class V>class value_equals {  private:    V value;  public:    // constructor (initialize value to compare with)    value_equals (const V& v)     : value(v) {    }    // comparison    bool operator() (pair<const K, V> elem) {        return elem.second == value;    }};int main(){    typedef map<float,float> FloatFloatMap;    FloatFloatMap coll;    FloatFloatMap::iterator pos;    // fill container    coll[1]=7;    coll[2]=4;    coll[3]=2;    coll[4]=3;    coll[5]=6;    coll[6]=1;    coll[7]=3;    // search an element with key 3.0    pos = coll.find(3.0);                     // logarithmic complexity    if (pos != coll.end()) {        cout << pos->first << ": "             << pos->second << endl;    }    // search an element with value 3.0    pos = find_if(coll.begin(),coll.end(),    // linear complexity                  value_equals<float,float>(3.0));    if (pos != coll.end()) {        cout << pos->first << ": "             << pos->second << endl;    }}
运行结果:

3: 24: 3请按任意键继续. . .