詳解C++ STL set 容器
本篇隨筆簡單介紹一下\(C++STL\)中\(set\)容器的使用方法及常見使用技巧。
set容器的概念和性質
\(set\)在英文中的意義是:集合。\(set\)容器也的確“人如其名”,實現了這個集合的功用。
高中數學必修一集合那章(高一以下的小伙伴不用慌,不講數學只講概念),關於集合的性質,給出了三個概念:無序性、互異性、確定性。
那么,\(set\)容器的功用就是維護一個集合,其中的元素滿足互異性。
我們可以將其理解為一個數組。這個數組的元素是兩兩不同的。
這個兩兩不同是指,如果這個\(set\)容器中已經包含了一個元素\(i\),那么無論我們后續再往里假如多少個\(i\),這個\(set\)中還是只有一個元素\(i\),而不會出現一堆\(i\)的情況。這就為我們提供了很多方便。
但是,需要額外說明的是,剛剛說集合是有無序性的,但是\(set\)中的元素是默認排好序(按升序排列)的。(稍微說一句,\(set\)容器自動有序和快速添加、刪除的性質是由其內部實現:紅黑樹(平衡樹的一種)。這個東西過於高深我不會,所以不予過多介紹,有興趣的小伙伴可以自行瀏覽相關內容。)
set容器的聲明
\(set\)容器的聲明和大部分\(C++STL\)容器一樣,都是:容器名<變量類型> 名稱的結構。前提需要開#include
#include<set>
set<int> s;
set<char> s;
set<pair<int,int> > s;
set<node> s;
struct node{...};
set容器的使用
其實,\(C++STL\)容器的使用方式都是差不多的。我們完全可以舉一反三地去類比。與\(bitset\)重定義了許多奇形怪狀新的函數之外,其他都是大致相同的。所以筆者在此不再做幼稚的介紹,大家都是競賽狗,應該都能自己看明白。
s.empty();
\(empty()\)函數返回當前集合是否為空,是返回1,否則返回0.
s.size();
\(size()\)函數返回當前集合的元素個數。
s.clear();
\(clear()\)函數清空當前集合。
s.begin(),s.end();
\(begin()\)函數和\(end()\)函數返回集合的首尾迭代器。注意是迭代器。我們可以把迭代器理解為數組的下標。但其實迭代器是一種指針。這里需要注意的是,由於計算機區間“前閉后開”的結構,\(begin()\)函數返回的指針指向的的確是集合的第一個元素。但\(end()\)返回的指針卻指向了集合最后一個元素后面一個元素。
s.insert(k);
\(insert(k)\)函數表示向集合中加入元素\(k\)。
s.erase(k);
\(erase(k)\)函數表示刪除集合中元素\(k\)。這也反映了\(set\)容器的強大之處,指哪打哪,說刪誰就刪誰,完全省略了遍歷、查找、復制、還原等繁瑣操作。更不用像鏈表那種數據結構那么毒瘤。直接一個函數,用\(O(logn)\)的復雜度解決問題。
s.find(k);
\(find(k)\)函數返回集合中指向元素\(k\)的迭代器。如果不存在這個元素,就返回\(s.end()\),這個性質可以用來判斷集合中有沒有這個元素。
其他好用的函數
下面介紹一些不是很常用,但是很好用的\(set\)容器的內置函數
s.lower_bound(),s.upper_bound();
熟悉\(algorithm\)庫和二分、離散化的小伙伴會對這兩個函數比較熟悉。其實這兩個函數比較常用。但是對於\(set\)集合來講就不是很常用。其中\(lower\_bound\)返回集合中第一個大於等於關鍵字的元素。\(upper\_bound\)返回集合中第一個嚴格大於關鍵字的元素。
s.equal_range();
這個東西是真的不常用...可能是我太菜了。
這個東西返回一個\(pair\)(內置二元組),分別表示第一個大於等於關鍵字的元素,第一個嚴格大於關鍵字的元素,也就是把前面的兩個函數和在一起。如果有一個元素找不到的話,就會返回\(s.end()\)。