1. set/multiset容器
1.1 set容器基本概念
Set的特性是。所有元素都會根據元素的鍵值自動被排序。Set的元素不像map那樣可以同時擁有實值和鍵值,set的元素即是鍵值又是實值。Set不允許兩個元素有相同的鍵值。
我們可以通過set的疊代器改變set元素的值嗎?不行,因為set元素值就是其鍵值,關系到set元素的排序規則。如果任意改變set元素值,會嚴重破壞set組織。換句話說,set的iterator是一種const_iterator.
set擁有和list某些相同的性質,當對容器中的元素進行插入操作或者删除操作的時候,操作之前所有的疊代器,在操作完成之後依然有效,被删除的那個元素的疊代器必然是一個例外。
1.2 multiset容器基本概念
multiset特性及用法和set完全相同,唯一的差别在于它允許鍵值重複。set和multiset的底層實作是紅黑樹,紅黑樹為平衡二叉樹的一種。
樹的簡單知識:
二叉樹就是任何節點最多隻允許有兩個位元組點。分别是左子結點和右子節點。

二叉搜尋樹,是指二叉樹中的節點按照一定的規則進行排序,使得對二叉樹中元素通路更加高效。二叉搜尋樹的放置規則是:任何節點的元素值一定大于其左子樹中的每一個節點的元素值,并且小于其右子樹的值。是以從根節點一直向左走,一直到無路可走,即得到最小值,一直向右走,直至無路可走,可得到最大值。那麼在兒茶搜尋樹中找到最大元素和最小元素是非常簡單的事情。下圖為二叉搜尋樹:
上面我們介紹了二叉搜尋樹,那麼當一個二叉搜尋樹的左子樹和右子樹不平衡的時候,那麼搜尋依據上圖表示,搜尋9所花費的時間要比搜尋17所花費的時間要多,由于我們的輸入或者經過我們插入或者删除操作,二叉樹失去平衡,造成搜尋效率降低。
是以我們有了一個平衡二叉樹的概念,所謂的平衡不是指的完全平衡。
2. set常用API
2.1 set構造函數
set<T> st;//set預設構造函數:
mulitset<T> mst; //multiset預設構造函數:
set(const set &st);//拷貝構造函數
2.2 set指派操作
set& operator=(const set &st);//重載等号操作符
swap(st);//交換兩個集合容器
2.3 set大小操作
size();//傳回容器中元素的數目
empty();//判斷容器是否為空
2.4 set插入和删除操作
insert(elem);//在容器中插入元素。
clear();//清除所有元素
erase(pos);//删除pos疊代器所指的元素,傳回下一個元素的疊代器。
erase(beg, end);//删除區間[beg,end)的所有元素 ,傳回下一個元素的疊代器。
erase(elem);//删除容器中值為elem的元素。
2.5 set查找操作
find(key);//查找鍵key是否存在,若存在,傳回該鍵的元素的疊代器;若不存在,傳回set.end();
count(key);//查找鍵key的元素個數
lower_bound(keyElem);//傳回第一個key>=keyElem元素的疊代器。
upper_bound(keyElem);//傳回第一個key>keyElem元素的疊代器。
equal_range(keyElem);//傳回容器中key與keyElem相等的上下限的兩個疊代器。
set的傳回值,指定set排序規則:
//插入操作傳回值
void test01(){
set<int> s;
pair<set<int>::iterator,bool> ret = s.insert(10);
if (ret.second){
cout << "插入成功:" << *ret.first << endl;
}
else{
cout << "插入失敗:" << *ret.first << endl;
}
ret = s.insert(10);
if(ret.second){
cout << "插入成功:" << *ret.first << endl;
}
else{
cout << "插入失敗:" << *ret.first << endl;
}
}
struct MyCompare02{
bool operator()(int v1,int v2){
return v1 > v2;
}
};
//set從大到小
void test02(){
srand((unsigned int)time(NULL));
//我們發現set容器的第二個模闆參數可以設定排序規則,預設規則是less<_Kty>
set<int, MyCompare02> s;
for (int i = 0; i < 10;i++){
s.insert(rand() % 100);
}
for (set<int, MyCompare02>::iterator it = s.begin(); it != s.end(); it ++){
cout << *it << " ";
}
cout << endl;
}
//set容器中存放對象
class Person{
public:
Person(string name,int age){
this->mName = name;
this->mAge = age;
}
public:
string mName;
int mAge;
};
struct MyCompare03{
bool operator()(const Person& p1,const Person& p2){
return p1.mAge > p2.mAge;
}
};
void test03(){
set<Person, MyCompare03> s;
Person p1("aaa", 20);
Person p2("bbb", 30);
Person p3("ccc", 40);
Person p4("ddd", 50);
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
for (set<Person, MyCompare03>::iterator it = s.begin(); it != s.end(); it++){
cout << "Name:" << it->mName << " Age:" << it->mAge << endl;
}
}
3.對組(pair)
//第一種方法建立一個對組
pair<string, int> pair1(string("name"), 20);
cout << pair1.first << endl; //通路pair第一個值
cout << pair1.second << endl;//通路pair第二個值
//第二種
pair<string, int> pair2 = make_pair("name", 30);
cout << pair2.first << endl;
cout << pair2.second << endl;
//pair=指派
pair<string, int> pair3 = pair2;
cout << pair3.first << endl;
cout << pair3.second << endl;