c++primer——關聯容器的使用
一、順序關聯容器
(一)、容器的種類
順序關聯容器有四種:
可以按照關鍵字是否重複分為兩類:
1、不重複:
map:儲存key-value
set:儲存key
2、可以重複:
multimap:儲存key-value
multiset:儲存key
(二)、關鍵字(key)的要求
1、關鍵字型別必須定義元素比較的方法,所提供的操作必須是嚴格弱序,即<=。
2、當我們想使用自定義的操作,必須在定義關聯容器型別是提供此操作的型別。尖括號內指出要定義哪種型別的容器,緊跟著自定義的操作型別。
尖括號中給出的型別僅僅是一個型別,當我們建立一個容器時,才會以建構函式的形式提供真正的比較操作。
eg:
//Sales_data
bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs){
return lhs.isbn() < rhs.isbn();
}
multiset<Sales_data, decltype(compareIsbn) *> bookstore(compareIsbn);
//or
multiset<Sales_data, bool(*) (const Sales_data &s1, const Sales_data &s2)> bookstore(compareIsbn);
//or
using compareType = bool(*)(const Sales_data& lhs, const Sales_data& rhs);
multiset<Sales_data, compareType*> bookstore(compareIsbn);
(三)、pair型別
定義在標頭檔案utility中。
類似容器,儲存兩個資料成員,用來生成特定型別的模板。可以對資料成員進行預設初始化,採用值初始化的方式。
pair的資料成員是public,分別命名為first,second。
pair(T1, T2) p; //宣告一個pair。
make_pair(v1,v2); // 返回一個用v1,v2初始化的pair。pair的型別從v1,v2推匯出來。
pair(T1,T2) p 宣告一個pair。
make_pair(v1,v2) 返回一個用v1,v2初始化的pair。pair的型別從v1,v2推匯出來。
(四)、關聯容器的操作
1、key_type 此容器型別的關鍵字型別
2、value_type 對於set,與key_type相同,對於map,為:pair<const key_type, mapped_type>
3、mapped_type 每個關鍵字關聯的型別;只適用於map
一、關聯容器迭代器
1、當解引用一個關聯容器迭代器時,可以得到一個型別為容器的value_type的值的引用。
對於map,first為一個const的關鍵字,second儲存成員值。set為一個const關鍵字。
2、通常不對關聯容器採取泛型演算法。因為關鍵字在迭代器解引用後返回的是const,無法修改與重排元素。因此,我們只可對關聯容器採取只讀演算法。但泛型演算法在這方面通常要對容器進行搜尋,關聯容器不能通過關鍵字快速查詢元素,因此不建議對關聯容器採用泛型演算法。
ps:最好採用關聯容器自帶的演算法。
二、新增元素
1、與其他容器的insert操作類似,map的操作注意傳入一對元素或者使用pair,make_pair。
2、檢測insert返回值,insert返回一個pair,first為一個迭代器,指向具有給定關鍵字的元素,second為一個bool值,本條是針對map和set來說。當關鍵字不重複插入成功時,bool返回一個true,當關鍵字已經存在時,返回一個false,insert什麼也不做。
三、刪除元素
c.erase(k); //從c中刪除每個關鍵字為k的元素,返回一個size_type值,指出刪除原色的數量
c.erase(p); //從c中刪除迭代器p指定的元素,返回一個指向配置後元素的迭代器。若p為尾元素,返回end()
c.erase(b, e); //刪除迭代器對b和e所表示的範圍中的元素。返回e
四、訪問元素
c.find(k); //返回一個迭代器,指向第一個關鍵字為k的元素,若k不再其中返回end()
c.count(k); //返回關鍵字等於k的元素的數量。
c.lower_bound(k); //返回一個迭代器,指向第一個不小於k的元素
c.upper_bound(k); //返回一個迭代器,指向第一個關鍵字大於k的元素
c.equal_range(k); //返回一個迭代器pair,表示關鍵字等於k的元素的範圍。若k不存在,pair的兩個成員均為end()
1、當我們訪問一個元素但不想改變原有容器的話,我們應採用find來代替下標訪問。
2、可以用find配合count來訪為multimap和multiset中相同關鍵字下的元素,count返回值用來表示範圍
3、遍歷容器時,我們可以採用lower_bound與upper_bound來表示一個迭代器範圍。若容器中沒有這個元素,則這兩個返回相等的迭代器,指向一個不影響排序的關鍵字的插入位置。
4、也可以用equal_range來代替第三條。
五、map的下標操作
1、若在元素中不存在該元素,則會為map建立一個元素,並進行值初始化。
2、我們只可以對非const的map使用下標操作。
3、當對一個map進行下標操作時,會獲得一個mapped_type物件,與解引用迭代器返回的物件不同。
六、p381 練習11.14
#include<iostream>
#include<map>
#include<set>
#include<string>
#include<algorithm>
#include<vector>
#include<string>
#include<list>
#include<utility>
using namespace std;
pair<string, int> process(string &s,int &n) {
if (!s.empty()) {
return{ s,n };
}
else {
return make_pair(s, n);
}
}
int main() {
//家庭名字以及孩子名字以及生日
map<string, vector<pair<string,int>>> family;
pair<string, int> ChildAndBirth;
//set<string> exclude = { "0" };
string firstName, childName;
int Birthday;
ostream &os = cout;
while ([&firstName, &os]() ->bool
{os << "please input your family name: "; return cin >> firstName && (firstName != "end"); }()) {
while ([&childName, &Birthday, &os]()->bool
{os << "please input your childname and birthday: "; return (cin >> childName >> Birthday) && (childName != "end"); }()) {
ChildAndBirth = process(childName, Birthday);
family[firstName].push_back(ChildAndBirth);
}
}
map<string, vector<pair<string,int>>> ::iterator it;
for (it = family.begin(); it != family.end(); ++it) {
cout << (*it).first << " ";
vector<pair<string, int>> ::iterator it1 = it->second.begin();
for (; it1 != it->second.end(); ++it1) {
cout << (*it1).first << " " << (*it1).second << endl;
}
}
return 0;
}
二、無序容器
unordered_map
unordered_set
unordered_multimap
unordered_multiset
1、使用hash函式和關鍵字型別==來阻止元素。
2、當關鍵字元素沒有明顯的序列關係或者維護序的代價非常高昂時,使用無序容器很有用
3、提供了與有序容器相同的操作
4、無序容器在儲存組織上為一組桶。每個桶儲存零個或多個元素。無序容器使用一個hash函式將元素對映到桶。
//桶介面
c.bucket_count() //正在使用的桶的數目
c.max_buck_count() //容器能容納得最多的桶的數量
c.bucket_size(n) //第n個桶中有多少個元素
c.bucket(k) //關鍵字為k的元素在哪個桶中
//桶迭代
local_iterator //可以用來訪問桶中元素的迭代器型別
const_local_iterator //桶迭代器的const版本
c.begin(n),c.end(n) //桶n的首元素迭代器和尾後迭代器
c.cbegin(n),c.cend(n) //與前兩個函式類似,但返回const_local_iterator
//雜湊策略
c.load_factor() //每個桶的平均元素數量,返回float值
c.max_load_factor() //c試圖維護桶的平均大小,返回float值。c會在需要時新增新的桶,使load_factor<=max_load_factor
c.rehash(n) //重新儲存,使bucket_count >= n且bucket_count > size/max_load_factor
c.reserve(n) //重新儲存,是的c可以儲存n個元素且不必rehash
5、標準庫為內建型別,提供了hash模板,還有一些標準庫型別,包括string和智慧指標定義了hash,我們可以直接定義關鍵字為內建型別、string、智慧指標的無序容器
6、不能直接定義關鍵字型別為自定義型別的無序容器。我們必須提供我們自己的hash模板版本。
相關文章
- C++ Qt開發:使用關聯容器類C++QT
- 【Effective STL(3)】關聯容器
- 資料結構——關聯容器資料結構
- 關聯條件的業務使用
- 標識使用者 使用者關聯 IDM 全域使用者關聯
- 容器雲資源資料關聯與資料聯動的難點和解決思路
- C++學習隨筆——關聯容器的迭代器失效問題C++
- 模型關聯使用總結模型
- 簡述Spring容器與SpringMVC的容器的聯絡與區別SpringMVC
- C++Primer 中文版pdfC++
- 容器間互聯(1)
- 關注容器安全!使用普通使用者身份跑 Python 程式Python
- dblink的關聯與本地關聯差異
- 表的關聯關係
- C++primer第一章C++
- Container容器元件的使用AI元件
- 使用多個鍵做模型關聯模型
- C++ 容器vector的使用C++
- 按月分表如何使用 Laravel 關聯模型Laravel模型
- 1.1.1. 關於CDB中的容器
- Docker框架的使用系列教程(四)容器的使用Docker框架
- Hibernate 的關聯關係對映
- 有關模型關聯的問題模型
- 10個必須掌握的PHP關聯陣列使用技巧PHP陣列
- C++Primer 第六章 函式C++函式
- C++Primer 第四章 表示式C++
- Laravel Eloquent 分表方法並使用模型關聯Laravel模型
- UserService 新增使用者關聯索引 addUserPermission 分析索引
- 使用延遲關聯實現高效分頁
- 關於STL容器的簡單總結
- Docker——理解好映象和容器的關係Docker
- Docker--容器和映象的使用Docker
- docker 容器的使用與檢視Docker
- STL使用篇__容器
- Postgresql容器使用SQL
- 使用關聯模型的鏈式呼叫時-有無括號的區別模型
- 關於模型關聯 獲取不到關聯資訊 求教模型
- Join關聯聯絡案例