set可能算是一種比較冷門的stl容器了,
喜歡用它的人覺得set真牛逼
不喜歡它的人覺得set真垃圾
很不幸,我屬於第一種
set作為一種封裝好的資料容器
最吸引人的地方是它的自動排序功能
這也就是說你可以擁有乙個實時的排好序的序列
或者可以用乙個序列同時實現大根堆和小根堆
時間複雜度和空間都是兩者和的1/2
善於運用set的自動排序特性可以為解題省去不少麻煩
啊就爽,就很爽。
繼承stl容器的傳統
set也有它自己專屬的標頭檔案
這個標頭檔案內包含兩種容器
set和multiset
set是自動排序還附帶去重的序列(有序集合),其中的元素不可重複
multiset是自動排序不去重的序列(有序多重集),其中可以有許多相同的元素
個人感覺在實際oi問題中比較常用的是multiset這種不去重的
兩者的實現原理都是一顆我不會打的紅黑樹,它們支援的函式基本相同
步入正題
首先我們來看一下怎麼宣告乙個set和multiset並往其中插入元素
#include #includeusing
namespace
std;
struct
node ;
bool
operator
<(const node &a, const node &b)
intmain()
當然,你也可以這麼寫(友元版)
與上面的寫法沒有什麼區別,但是友元比較難理解點
#include #includeusing
namespace
std;
struct
node
setfuc;
}; intmain()
這樣就完成了以普通資料型別和結構體的sethemultiset的宣告
同時切記:set和multiset內的資料型別必須已定義小於號
學完了宣告就該學如何往容器內插入元素
(size函式,empty函式,clear函式在set中也有,與在vector中作用無異,故此處不提)
與vector不同,往set內插入元素不需要指定位置
元素進入set後自動根據「<」的定義找到自己的位置
set和multiset都使用insert函式插入元素
時間複雜度為o(logn)
**如下
#include #includeusing
namespace
std;
intx;
intmain() }
如此即可實現向set p和multiset q中插入n個元素
插入完元素後我們可以對這些元素進行操作
首先需要注意的是set不支援隨機訪問
也就是說不能通過下標的方式訪問set中的元素
想想也很好理解,即使這貨能用下標你也不知道排完序後哪個元素是哪個
所以set給了我們與之替代的兩種資料查詢方式
迭代器(可以理解為stl的指標)和find函式
set的迭代器宣告方式與在vector中的宣告方式無異
同樣是宣告乙個名為it的迭代器
有set::iterator it;
如果++it,
則it指向set中的下乙個元素
因為set是有序集合,所以++it所表示的元素就是剛好比it所指向的元素大的第乙個元素
同時set也有begin和end函式用來取隊首和隊尾(的迭代器)
begin在set中取的是最小元素的迭代器
end函式跟vector中一樣返回隊尾下個元素的迭代器
所以--end()表示的是隊尾元素的迭代器
我們看一段遍歷set的**來幫助我們理解這些抽象的概念
#include #includeusing
namespace
std;
intmain()
程式輸出結果是
set 中的元素依次是 123multiset 中的元素依次是 11
23
在這個例子中我們可以了解到set中迭代器的用法和set與multiset的本質區別
有助於我們搞明白並在程式上實現set的基本操作
了解了迭代器
我們再來看看我認為能與迭代器平起平坐幫了大忙的find函式
find函式能夠找到set中大小為x的元素並返回指向該元素的迭代器。
如果set中並不存在元素x則返回s.end()
x 多次出現則返回第一次出現時的迭代器
樣例如下
#include #includeusing
namespace
std;
intmain()
聰明的你已經看出來了
我這麼寫返回的一定是要查詢的那個數
其實就是沒屁用
啊就有的題可能會出現需要用到find函式的地方(裝不下去了)
在實際應用中,我們需要對不需要的元素進行刪除
set給了我們乙個強大的資料刪除函式erase()
括號內既可以是乙個迭代器
erase刪除這個迭代器所指的元素
括號內也可以是個值或者啥東西
erase在set或multiset中查詢並刪除和括號內這個東西一樣的全部元素
那問題來了
在用multiset解決實際問題時
很多情況下我們並不想把所有相同的元素都刪除
只想刪除乙個兩個或幾個(erase說沒門兒
此時find函式突然出現
「勞資返回的是迭代器hahahahaha」
於是你就可以用find函式定位到元素x第一次出現的位置並返回此時的迭代器
再用erase通過迭代器刪除的功能刪除這個x
由於multiset恒為有序所以刪除哪個x無關緊要
反正修改後的multiset都一樣
所以我們就解決了這個問題(find函式大放異彩)
最後要介紹的是count函式和lower_bound/upper_bound這三個函式
首先count函式在multiset中比較常見(set裡根本不能用)
count(x)返回multiset中x的出現次數(在set裡用肯定返回0或1,可以作為判斷元素是非在集合內的方法,比遍歷慢一點)
目前還沒有碰到過需要用count這個函式的題(我可能直接遍歷了?大霧)
lower_bound/upper_bound是二分函式,在其他stl容器中也有出現
跟find函式類似
lower_bound(x)返回的是》=x的元素中最小的乙個
upper_bound(x)返回的是》x的元素中最小的乙個
當然你也可以用find+迭代器完成這一項功能
不過難寫一點,而且lower_bound和upper_bound的時間複雜度和find一樣為
o(logn)
所以二分的時候何樂而不為呢?
知識點 C 中STL容器之set
零 stl目錄 1 容器之map 2 容器之vector 3 容器之set 一 前言 繼上期的vector之後,我們又迎來了另乙個類陣列的stl容器 set。二 用途與特性 set,顧名思義,集合,由數學知識可知,其內部每個元素最多出現一次。同時,系統能夠根據元素的值自動進行排序。和set一樣,mu...
c STL容器(2)set容器
set翻譯為集合,是乙個內部自動有序且不含重複元素的容器 set的定義 set typename name set int vi set double vi set char vi set vi node可以是結構體 set int a 100 陣列裡面每個元素都是乙個set集合insert x 將...
初級總結 容器2 Set介面
介紹完了list介面,我們來看看set介面。set介面 內部不可重複。set介面有兩個重要的實現類 hashset和treeset。hashset屬於無序,雜湊存放,需要重寫equals和hashcode方法 hashcode相等,equals 內容 不一定相等 equals 內容 相等,hashc...