我不熟悉的set
我不熟悉的set
同樣的我著重介紹那些我不怎麼用到的系列,同時,常用的我就點一下。
我們都知道set底層是用紅黑樹實現的,紅黑樹是一種已排序的樹,所以我們通過迭代器來訪問節點元素的時候,並不可以改變它,如果隨意改變,那排序規則就亂套了。
講API之前,現介紹一個 對組(pair) 的概念。
對組(pair)將一對值組合成一個值,這一對值可以具有不同的資料型別,兩個值可以分別用pair的兩個公有屬性first和second訪問。
建立對組的方法
一、使用拷貝構造
pair<string, int> pair1(string("name"), 20); cout << pair1.first << endl; //訪問pair第一個值 cout << pair1.second << endl;//訪問pair第二個值
二、使用make_pair
pair<string, int> pair2 = make_pair("name", 30);
cout << pair2.first << endl;
cout << pair2.second << endl;
對組可以方便的將不同資料型別作為返回值,一次返回兩個數值。
構造,賦值和大小操作
set<T> st; //set預設建構函式。 set(const set &st); //拷貝建構函式 swap(set st); //交換兩個集合容器 size(); //返回容器中元素的數目 empty(); //判斷容器是否為空
與前幾篇說的一致。
插入與刪除
pair<iterator,bool> insert(elem); //在容器中插入元素。
void insert(beg,end) //插入[beg,end)範圍元素
iterator erase(pos); //刪除pos迭代器所指的元素,返回下一個元素的迭代器。
iterator erase(beg, end);//刪除區間[beg,end)的所有元素 ,返回下一個元素的迭代器。
size_type erase(elem); //刪除容器中值為elem的元素。
void clear(); //清除所有元素
這邊強調一下erase和insert:
關於erase:
- 既可以刪除迭代器指向的元素,也可以刪除指定的元素值。與list一致。
- 刪除迭代器的時候返回指向的下一個迭代器。
- 刪除指定元素的時候,返回的是這個元素在容器中的個數。(set為0或1,multiset可以大於1)
關於insert:
- 唯一的一個插入元素的動作。
- 插入元素時,返回一個對組。第一個成員是指向新插入值或已存在的這個值的迭代器,第二個成員表示插入成功與否(不存在的,新插入的為真,已存在的不需新插入為假)。
- 範圍插入的時候,沒有返回值。
查詢函式
這才是今天的重點。
iterator find(key); //查詢鍵key是否存在,若存在,返回該鍵的元素的迭代器;若不存在,返回set.end();
size_type count(key); //查詢鍵key的元素個數
iterator lower_bound(keyElem);//返回第一個key>=keyElem元素的迭代器。
iterator upper_bound(keyElem);//返回第一個key>keyElem元素的迭代器。
pair<iterator,iterator> equal_range(keyElem);//返回容器中key與keyElem相等的上下限的兩個迭代器。
find函式
find函式,實際上是在紅黑樹中進行二叉搜尋,如果找到了就返回相應位置迭代器,找不到就返回尾後迭代器end().
count函式
根據set不能重複的性質,count非零即一。
lower_bound,upper_bound和equal_range函式
很直接的,lower就是返回第一個大於等於指定元素的迭代器,而upper就是返回第一個大於指定元素的迭代器。如下所示:
int main()
{
set<int> s;
s.insert(2);
s.insert(4);
s.insert(9);
s.insert(10);
s.insert(20);
auto it1 = s.lower_bound(9);
auto it2 = s.upper_bound(9);
cout << "*it1=" << *it1 << " *it2=" << *it2 << endl;
return 0;
}
我們輸出結果為:
*it1=9 *it2=10
由此可以清楚看出這兩個函式的作用。
接下來我們介紹equal_range函式。equal_range的作用就是返回查詢到的元素的上下限迭代器,同樣遵守左閉右開的原則。而這正好是我們lower_bound和upper_bound的返回值。所以,我們可以將equal_range的返回值看做是返回一個存著lower_bound和upper_bound的返回值的對組。
我們可以驗證:
int main()
{
//multiset<int> s;
set<int> s;
s.insert(2);
s.insert(4);
s.insert(9);
s.insert(9);
s.insert(9);
s.insert(10);
s.insert(20);
auto it1 = s.lower_bound(9);
auto it2 = s.upper_bound(9);
auto pair = s.equal_range(9);
if (pair.first == it1 && pair.second == it2)
cout << "equal_range pair == lower_bound & upper_bound" << endl;
return 0;
}
最後我們成功輸出了
"equal_range pair == lower_bound & upper_bound"
set的排序規則
set預設是從小到大排序的,當我們要從大到小排序或者用自定義資料排序的時候,我們就要指定排序規則,同樣也是使用仿函式實現:
//functor為仿函式
set<int,functor> s;
...
自己寫一個仿函式即可。可參照 我不熟悉的list .
不支援回撥函式。
速記:因為set用紅黑樹實現,插入即排序,排序一旦建立不能更改,所以要在建立set的時候就指定排序規則,而不是插入完了之後再指定。
由於set的特殊性,插入即排序建立。故有此要求。