關聯容器和順序容器的本質區別:關聯容器是通過鍵存取和讀取元素、順序容器通過元素在容器中的位置順序存儲和訪問元素。因此,關聯容器不提供front、push_front、pop_front、back、push_back以及pop_back,此外對於關聯容器不能通過容器大小來定義,因為這樣的話將無法知道鍵所對應的值什麼。
兩個基本的關聯容器類型是map和set。map的元素以鍵-值對的形式組織:鍵用作元素在map的索引,而值則表示所存儲和讀取的數據。set僅包含一個鍵,並有效地支持關於某個鍵是否存在的查詢。set和map類型的對象不允許為同一個鍵添加第二個元素。如果一個鍵必須對應多個實例,則需使用multimap或mutiset類型,這兩種類型允許多個元素擁有相同的鍵。
在介紹關聯容器之前,必須先介紹一種與它相關的簡單的標准庫類型--pair類型:
pair類型的初始化-------在頭文件utility中
pair<T1,T2> p1; 創建一個pair對象,兩個元素的類型分別是T1,T2類型,采用初值進行初始化
pair<T1,T2> p1(v1,v2); 創建一個pair對象,兩個元素的類型分別是T1,T2類型,采用v1,v2分別進行初始化
make_pair(v1,v2); 以v1、v2的只進創建一個pair對象,類型分別是v1、v2的類型
p.first 返回p中第一個公有數據成員
p.second 返回p中第二個公有數據成員
pair使用:
#include<utility>
pair<string,int> author("Peter",30);
cout<<author.first<<"\t"<<author.second<<endl;//可以直接訪問數據成員
//使用typedef進行簡化
typedef pair<string,string> Student;
Student s1,s2("aaa","bbb");
s1.first="ccc";
s1.second="ddd";
//使用make_pair函數生成一個新的pair對象
string first="eee",second="fff";
Student s3=make_pair(first,second);
map 關聯數組,通過鍵來存儲和讀取
map 初始化:
map<k,v> m1 創建一個名m的空的map對形象,對其鍵和值的類型分別為k、v
map<k, v> m(m2) 創建m2的副本m,m與m2的類型必須相同的鍵值類型和值類型
map<k,v> m(b,e) 創建map類型的對象m,存儲迭代器b和e標記范圍內所有元素的副本,元素的類型必須轉換為pair<const k, v>
map定義的類型:
map<K,V>::key_type 在map中用做索引的鍵的類型
map<K,V>::mapped_type 在map中鍵所關聯的值的類型
map<K,V>::value_type 一個pair類型,它的first元素具有const map<K,V>::key::type 類型,而second元素則為map<K,V>::mapped_type類型
map迭代器進行解引用將產生pair類型的對象,如:
map<string,int>::iterator map_it = word_count.begin();
cout<<map_it->first<<""<<map_it->second<<endl;
給map添加成員:
使用下標訪問map對象:在map對象查找鍵值為x的元素如果找到則返回它的值(類型是map<k,v>::mapped_type),否則插入一個新的對象鍵值為x,值為map<k,v>中v的默 認初值。因此,使用下標訪問map與使用下標訪問數組或vector的行為不同,用下標訪問不存在的元素將導致在map容器中添加一個新的元素,它的鍵即為該下標值。這一特性可以使程序簡練:
map<string,int> word_count;
word_count["Peter"]=10;//相當於增加一個鍵值對
//創建一個map對象,用來記錄每個單詞出現的次數,十分簡潔。
//因為如果讀取的是一個新單詞,則將在word_count中添加以該單詞為索引的新元素
map<string,int> word_count;
string word;
while(cin>>word)
{
++word_count[word];
}
使用Insert對map進行插入:
m .insert(e) e是一個用在m上的value_type類型的值,如果e.first不在m中則插入一個值為.second的新元素,否則該鍵值在m中已經存在則保持不變,該
函數返回一個pair新類型,包含一個指向鍵值為e.first的元素的map迭代器,以及一個bool類型的對象,表示是否插入該元素
m.insert(beg,end) 插入beg、end標記范圍內的元素,如果該元素的m.first已經存在則不插入否則插入。返回void類型
m.insert(iter,e) 如果e.first不在m中,則創建新元素,並以迭代器iter為起點搜索新元素的存儲位置,否則返回一個迭代器,指向m中具有的給定鍵的元素。
//用insert方法重寫單詞統計程序
map<string,int> word_count;
word_count.insert(map<string,int>::value_type("aaa",1));
map<string,int> word_count;
string word;
while(cin>>word)
{
pair<map<string,int>::iterator,bool> ret=word_count.insert(make_pair<string,int>(word,1));
if(!ret.second)//如果沒插入成功,證明原來已經存在鍵值,將統計值+1
{
++ret.first->second;// first是一個迭代器,指向插入的鍵
}
}
查找和讀取map中的元素:
m.count(k) 返回k在m中出現的次數,在map中只是返回0、1
m.find(k) 如果k在m中的鍵值存在則返回相應的迭代器,否則返回超出來末端迭代器
//讀取元素而又不插入新元素
int occurs;
map<string,int>::iterator it= word_count.find("foobar");//不存在,則返回end迭代器
if(it!=word_count.end())//可能找不到
{
occurs=it.second;
}
從map中刪除元素 ,使用erase與順序容器功能一樣:
m.erase(k) 刪除m中鍵為k的元素。返回值為被刪除元素的個數,對於map容器而言,其值必然是0或1。
m.erase(p) 從m中刪除迭代器p所指向的元素。返回值為void類型。
m.erase(b,e) 從m中刪除一段由一對迭代器范圍的元素。返回值為void類型。
map對象的迭代遍歷:
map<string,int> word_count;
map<string,int>::const_iterator iter = word_count.begin();
while(iter!=word_count.end())
{
cout<<iter->second<<endl;
iter++;
}
set類型
Set的作用就是排序。每個元素的值不能直接被改變。 它是一個容器,它用於儲存數據並且能從一個數據集合中取出數據。它的每個元素的值必須惟一,而且系統會根據該值來自 動將數據排序。每個元素的值不能直接被改變。
大小可變的集合,支持通過鍵值實現的快速讀取。對於單純想知道一個值是否存在則set容器最適用
在set容器中value_type不是pair類型,而是與key_value的類型相同,它的鍵值類型也是唯一的且不能修改
在set也支持find、count、insert、erase操作
在set中添加元素:;
set<int> set1;
pair<set<int>::iterator,bool> p=set1.insert(1);//返回pair類型對象,包含一個迭代器和一個布爾值
set1.insert(2);
int arr[]={1,2,3};
set<int> set2;
set2.insert(arr,arr+3);//返回void類型
從set中獲取元素:與map方法使用類似,使用find和count函數。