程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> [C++ 面試基礎知識總結] 關聯容器

[C++ 面試基礎知識總結] 關聯容器

編輯:關於C++

關聯容器類型

標准庫共提供了8個關聯容器
map 關聯數組:保存關鍵字-值對
set 關鍵字即值,即只保存關鍵字的容器
multimap 關鍵字可重復出現的map
multiset 關鍵字可重復出現的set
unordered_map 用哈希函數組織的map
unordered_set 用哈希函數組織的set
unordered_multimap 用哈希函數組織,關鍵字可重復出現的map
unordered_multiset 用哈希函數組織,關鍵字可重復出現的set

map是關鍵字-值對的集合,通常被稱為關聯數組。關聯數組與正常數組類似,不同之處在於其下標不必是整數,是一個關鍵字。而set就是關鍵字的簡單集合。

關聯容器概述

定義關聯容器

    // 初始化map時,必須提供關鍵字類型和值類型。每個關鍵字-值對書寫格式為{ key,value}
    map scores = {{"Summer",80},{"Seven",90},{"Leg",60}};
    set names = {"Summer","Seven","Leg"};

map和set的關鍵字必須是唯一的,而multimap和multiset沒有此限制

   //定義一個有20個元素的vector,保存0-9每個整數的兩個拷貝
    vector v;
    for (int i = 0; i != 10; ++i) {
        v.push_back(i);
        v.push_back(i);
    }

    //用vetor初始化set和multiset (關聯容器支持容器通用的初始化,賦值和操作)
    set iset(v.begin(),v.end());
    multiset miset(v.begin(),v.end());

    cout << iset.size() << endl;  //結果為10
    cout << miset.size() << endl;  //結果為20

關鍵字類型的要求

有序關聯容器的關鍵字類型必須定義元素比較的方法,默認情況下,標准庫使用關鍵字類型的<運算符來比較兩個關鍵字。也提供一個自定義的運算符。所提供的操作必須在關鍵字類型上定義一個嚴格弱序。即具備以下性質:
1.兩個關鍵字不能同時“小於等於”對方。
2.如果k1“小於等於”k2,且k2“小於等於”k3,那麼k1必須“小於等於”k3。
3.如果存在兩個關鍵字,任何一個都不“小於等於”另一個,那麼兩個關鍵字“等價”,如果k1“等價於”k2,且k2“等價於”k3,那麼k1必須“等價於”k3。

pair

pair定義在頭文件utility中,一個pair保存兩個數據對象,類似容器,創建pair時必須提供兩個類型名,pair的數據成員將具有對應的類型。

    //將一個map容器中的元素保存到一個元素類型為pair的vector中
    map scores = {{"Summer",80},{"Seven",90},{"Leg",60}};
    vector> v;

    for(const auto &score : scores){
        //初始化一個pair,first和second分別為鍵值對中的關鍵字和值
        pair p (score.first,score.second);
        v.push_back(p);
    }

    for (const auto &p : v) {
        //pair的first和second分別為pair中的兩個數據成員 輸出結果Leg 60 Seven 90 Summer 80 (map已根據關鍵字自動排序)
        cout << p.first << " " << p.second << " ";
    }
    cout << endl;

關聯容器操作

關聯容器迭代器

map和set的關鍵字都為常量,不能改變。

    map scores = {{"Summer",80},{"Seven",90},{"Leg",60}};
    // mapIt類型為map::iterator,指向類型為pair的對象
    auto mapIt = scores.begin();
    while (mapIt != scores.end()) {
        //不能改變map關鍵字,但可以改變值
        cout << mapIt->first << " " << ++(mapIt++->second) << endl;
    }

    set names = {"Summer","Seven","Leg"};
    //setIt類型為set::iterator,指向類型為const string的對象
    for (auto setIt = names.begin(); setIt != names.end(); ++setIt) {
        //只能讀取set關鍵字,不能改變
        cout << *setIt << endl;
    }

注意:由於關聯容器關鍵字的const屬性,不能講關聯容器傳遞給修改或重排容器元素的算法,所以通常不對關聯容器使用泛型算法。

添加元素

調用insert函數可向map或set中添加一個元素或一個范圍,若元素關鍵字已經存在,則不會有任何操作。

    set names = {"Summer","Seven","Leg"};
    names.insert("CannonFly");

    map scores = {{"Summer",80},{"Seven",90},{"Leg",60}};
    //以下4種寫法等價
    scores.insert({"CannonFly",85});
    scores.insert(make_pair("CannonFly", 85));
    scores.insert(pair("CannonFly",85));
    scores.insert(map::value_type("CannonFly",85));

insert函數的返回值類型pair<指向指定關鍵字的迭代器,bool(成功標志)>

例如上述map執行insert後返回的類型為pair

    map scores = {{"Summer",80},{"Seven",90},{"Leg",60}};
    auto ret = scores.insert({"CannonFly",85});

可以使用insert的返回值

ret.first ret的第一個成員,是一個map迭代器,指向具有給定關鍵字的元素
ret.first->  ret的第一個成員解引,提取map中的元素,元素是一個pair
ret.first->first  map中元素的關鍵字部分
ret.first->second  map中元素的值部分
ret.second  ret的第二個成員,是一個bool值,表示是否插入成功

對於multimap,multiset,insert函數不返回標志是否成功bool值,因為可以插入相同關鍵字的元素。

刪除元素

erase函數可以刪除指定關鍵字的元素,迭代器所指的元素或者某個范圍內的所有元素,返回值是實際刪除的元素。

    map scores = {{"Summer",80},{"Seven",90},{"Leg",60}};
    scores.erase("Summer");  //刪除map中關鍵字為Summer的元素
    scores.erase(scores.begin());  //刪除map中第一個元素
    scores.erase(scores.begin(),scores.end());  //刪除map中所有元素

訪問元素

map和unordered_map可以采取下標的方式對其中與關鍵字相關聯的值進行操作,而set只有關鍵字而沒有與其關聯的值,所以不支持下標。map下標的索引是關鍵字。

    map scores = {{"Summer",80},{"Seven",90},{"Leg",60}};
    scores["Summer"] = 85; 
    scores["CannonFly"] = 85;  // map中沒有該關鍵字,則創建一個元素插入到map中,並對關聯值初始化。   

除了下標之外,還有其他的查找元素的方法。

    map scores = {{"Summer",80},{"Seven",90},{"Leg",60}};
    scores.find("CannonFly");  //查找元素,找到返回該元素的迭代器,未找到返回尾後迭代器
    scores.count("Summer");  //返回元素在容器中出現的次數

    //下面是兩種在允許重復關鍵字的關聯容器中輸出所有同名關鍵字的操作
    multiset names = {"Summer","Seven","Leg","Summer"};
    //lower_bound返回第一個不小於給定值的元素,names.upper_bound返回第一個大於給定值的元素
    for (auto begin = names.lower_bound("Summer"), end = names.upper_bound("Summer"); begin != end; ++begin) {
        cout << *begin << endl;
    }
    // equal_range返回一個迭代器pair,表示等於給定值的元素的范圍
    for (auto pos = names.equal_range("Summer"); pos.first != pos.second; ++pos.first) {
        cout << *pos.first << endl;
    }

無序容器

無序關聯容器不是使用比較運算法來組織元素,而是用一個哈希函數和關鍵字類型的==運算法。通常無序容器和其對應的有序容器是可以相互替換的,只是由於元素未按順序存儲,無序容器的輸出通常會與有序容器不同。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved