C 知識點 STL容器2 set

2022-04-07 10:37:52 字數 3742 閱讀 2345

set可能算是一種比較冷門的stl容器了,

喜歡用它的人覺得set真牛逼

不喜歡它的人覺得set真垃圾

很不幸,我屬於第一種

set作為一種封裝好的資料容器

最吸引人的地方是它的自動排序功能

這也就是說你可以擁有乙個實時的排好序的序列

或者可以用乙個序列同時實現大根堆和小根堆

時間複雜度和空間都是兩者和的1/2

善於運用set的自動排序特性可以為解題省去不少麻煩

啊就爽,就很爽。

繼承stl容器的傳統

set也有它自己專屬的標頭檔案

這個標頭檔案內包含兩種容器

set和multiset

set是自動排序還附帶去重的序列(有序集合),其中的元素不可重複

multiset是自動排序不去重的序列(有序多重集),其中可以有許多相同的元素

個人感覺在實際oi問題中比較常用的是multiset這種不去重的

兩者的實現原理都是一顆我不會打的紅黑樹,它們支援的函式基本相同

步入正題

首先我們來看一下怎麼宣告乙個set和multiset並往其中插入元素

#include #include 

using

namespace

std;

struct

node ;

bool

operator

<(const node &a, const node &b)

intmain()

當然,你也可以這麼寫(友元版)

與上面的寫法沒有什麼區別,但是友元比較難理解點

#include #include 

using

namespace

std;

struct

node

setfuc;

}; intmain()

這樣就完成了以普通資料型別和結構體的sethemultiset的宣告

同時切記:set和multiset內的資料型別必須已定義小於號

學完了宣告就該學如何往容器內插入元素

(size函式,empty函式,clear函式在set中也有,與在vector中作用無異,故此處不提)

與vector不同,往set內插入元素不需要指定位置

元素進入set後自動根據「<」的定義找到自己的位置

set和multiset都使用insert函式插入元素

時間複雜度為o(logn)

**如下

#include #include 

using

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 #include 

using

namespace

std;

intmain()

程式輸出結果是

set 中的元素依次是 123

multiset 中的元素依次是 11

23

在這個例子中我們可以了解到set中迭代器的用法和set與multiset的本質區別

有助於我們搞明白並在程式上實現set的基本操作

了解了迭代器

我們再來看看我認為能與迭代器平起平坐幫了大忙的find函式

find函式能夠找到set中大小為x的元素並返回指向該元素的迭代器。

如果set中並不存在元素x則返回s.end()

x 多次出現則返回第一次出現時的迭代器

樣例如下

#include #include 

using

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...