天天看點

【C++Primer】第11章 關聯容器第11章 關聯容器

第11章 關聯容器

關聯容器按關鍵字來儲存和通路;與順序容器不同

【C++Primer】第11章 關聯容器第11章 關聯容器

11.1 使用關聯容器

map<string, size_t> word_count;
string word;
while(cin >> word){
    ++word_count[word];
}
for(const auto& w : word_count){
    cout << w.first << "出現" << w.second << "次" << endl;
}
           

11.2 關聯容器概述

關聯容器的疊代器都是雙向的

11.2.1 定義關聯容器

map<string, size_t> word_count;
set<string> exclude = {"the", "but", "and", "or"};  //清單初始化
map<string, string> authors = {
    {"Joyce", "James"},
    {"Austen", "Jane"},
    {"Dickens", "Charles"}
};
           
vector<int> ivec = {1,1,2,2,3,3,4,4};
set<int> iset(ivec.cbegin(), ivec.cend());
set<int> miset(ivec.cbegin(), ivec.cend());
cout << ivec.size() << endl;   //8
cout << iset.size() << endl;   //4
cout << miset.size() << endl;  //8
           

11.2.3 pair類型

pair<string string> a;
pair<string, size_t> b;
pair<string, vector<int>> line;

pair<string, string> author{"James", "Jotces"};  //初始化
           
【C++Primer】第11章 關聯容器第11章 關聯容器

11.3 關聯容器操作

【C++Primer】第11章 關聯容器第11章 關聯容器
set<string>::value_type v1;       //string
set<string>::key_type v2;         //string
map<string, int>::value_type v3;  //pair<const string, int>
map<string, int>::key_type v4;    //string
map<string, int>::mapped_type v5;  //int
           

11.3.1 關聯容器疊代器

【C++Primer】第11章 關聯容器第11章 關聯容器

我們通常不能對關聯容器使用泛型算法

set類型中元素是const的

map中的元素是pair,其第一個成員是是const的

使用關聯容器定義的專用find成員會比調用泛型find快得多

練習11.16

map<string, string>family;
map<const string, string>::iterator it;
it->first = "AAA";  //錯誤,const類型
it->second = "BBB";
           

練習11.17

v是一個string的vector,c是一個string的muitiset

copy(v.begin(), v.end(), inserter(c, c.end()));
copy(v.begin(), v.end(), back_inserter(c));   //錯誤, back_inserter建立一個使用push_back的疊代器
copy(c.begin(), c.end(), inserter(v, v.end()));
copy(c.begin(), c.end(), back_inserter(v));
           

練習11.18

11.3.2 添加元素

set兩種方式添加元素:

  • 一對疊代器
  • 清單初始化
vector<int> ivec = {2,4,6,8,2,4,6,8};
set<int> set2;
set2.insert(ivec.cbegin(), ivec.cend());  //4個元素
set2.insert({1,3,5,7,1,3,5,7});           //8個元素
           

map添加元素:

word_count.insert({word, 1});
word_count.insert(make_pair(word, 1));
word_count.insert(pair<string, size_t>(word, 1));
word_count.insert(map<string, size_t>::value_type(word, 1));
           
【C++Primer】第11章 關聯容器第11章 關聯容器

11.3.3 删除元素

關聯容器提供一個額外的erase操作,它接受一個key_type參數。此版本删除所有比對給定關鍵字的元素

對允許重複關鍵字的容器,删除元素的數量可能大于1

multimap<string, string> authors;
authors.insert({"Barth, John", "Sot"});
suthors.insert({"Barth, John", "Lost"});

auto cnt = authors.erase("Barth, John");
           
【C++Primer】第11章 關聯容器第11章 關聯容器

11.3.4 map的下标操作

【C++Primer】第11章 關聯容器第11章 關聯容器
map<int, int> m;
m[0] = 1;   //添加對組元素
           

11.3.5 通路元素

set<int> iset = {0,1,2,3,4,5,6,7,8,9};
iset.find(1);   //傳回一個疊代器,指向key==1的元素
iset.find(11);  //傳回一個疊代器,其值等于iset.end()
iset.count(1);  //傳回1
iset.count(11);  //傳回0
           

如果不需要計數最好用find

【C++Primer】第11章 關聯容器第11章 關聯容器

11.3.6 一個單詞轉換的map

//單詞轉換
void word_transform(ifstream& map_file, ifstream& input){
    auto trans_map = buildMap(map_file);  //儲存轉換規則
    string text;                          //儲存輸入中的每一行
    while(getline(input, text)){          //讀取一行輸入 
        istringstream stream(text);       //讀取每個單詞
        string word;
        bool firstword = true;            //控制是否列印空格
        while(stream >> word){
            //該if else控制列印空格
            if(firstword){
                firstword = false;
            }
            else{
                cout << " ";   //單詞間列印空格
            }
            
            //transform傳回它的第一個參數或其轉換之後的形式
            cout << transform(word, trans_map);  //列印輸出單詞
        }
        cout << endl;   //輸出完一行
    }
}

//建立轉換映射
map<string, string> buildMap(ifstream& map_file){
    map<string, string> trans_map;  //儲存轉換規則
    string key;
    string value;
    //讀取的第一個單詞存入key中,行中剩餘内容存入value中
    while(map_file >> key && getline(map_file, value)){
        if(value.size() > 1){
            trans_map[key] = value.substr(1);
        }
        else{
            throw runtime_error("no rule for" + key);
        }
    }
    return trans_map;
}

//生成轉換文本
const string& transform(const string& s, const map<string, string>& m){
    auto map_it = m.find(s);
    if(map_it != m.cend()){
        return map_it->second;   //找到則使用替換短語
    }
    else{
        return s;   //原string
    }
}
           

11.4 無序容器

  • unordered_map
  • unordered_set
【C++Primer】第11章 關聯容器第11章 關聯容器

繼續閱讀