1. 程式人生 > >C++ STL set(集合)

C++ STL set(集合)

函數 太多的 c++ stl tro 展示 最小 容器 for it!

引入
集合和映射也是兩個常用的容器。set就是數學上的集合——每個元素最多只出現一次。和sort一樣,自定義類型也可以構造set,但同樣必須定義“小於”運算符。

頭文件
#include<set>(當然,如果願意,你也可以用#include<bits/stdc++.h>這個萬能庫,但是會導致內存巨大。。。

聲明

set<int > s;//普通的定義(不允許元素重復)
struct rec{...};set<rec > s;//結構體
multiset<double > s;//(允許集合中元素重復)
//註意:set和multiset存儲的元素必須定義“小於號”運算符

size/empty/clear
與vector類似,分別為元素個數、是否為空、清空。前兩者的時間復雜度為\(O(1)\)

叠代器
set和multiset的叠代器稱為“雙向訪問叠代器”(類似於指針),不支持“隨機訪問”,支持星號“*"解除引用,僅支持“++”和“- -”兩個與運算相關的操作。
\(it\)是一個叠代器,例如set<int > :: iterator it;
若把\(it\)++,則\(it\)將會指向下一個元素。這裏的“下一個”是指在元素從小到大排序的結果中,排在\(it\)下一名的元素。同理,若把\(it\)- -,則\(it\)將會指向排在“上一個”的元素。

請註意,執行“++”和“- -”操作的時間復雜度都是\(O(log n)\)。執行操作前後,務必仔細檢查,避免叠代器指向的位置超出首、尾叠代器之間的範圍。

begin/end
返回集合的首、尾叠代器,時間復雜度為\(O(1)\)
s.begin() 是指向集合中最小元素的叠代器。
s.end() 是指向集合中最大元素的下一個位置的叠代器。換言之,就像 vector 一樣,是一個“前閉後開”的形式。因此 - -end() 是指向集合中最大元素的叠代器。

insert
s.insert(x) 把一個元素 x 插入到集合 s 中,時間復雜度為\(O(log n)\)
在 set 中,若元素已存在,則不會重復插入該元素,對集合的狀態無影響。

下面的代碼把 n 個整數插入有序多重集 multiset ,並從小到大輸出,時間復雜度\(O(n log n)\),相當於進行了一次排序。假設 n 個整數目前存儲在數組 a[1~n]中。

multiset<int > s;
for(int i=1;i<=n;i++)s.insert(a[i]);
for(multiset<int > :: iterator it=s.begin();it!=s.end();it++)
cout<<*id<<endl;

find
s.find(x) 在集合s中查找等於 x 的元素,並返回指向該指針的叠代器。若不存在,則返回 s.end() 。時間復雜度\(O(log n)\)

lower_bound/upper_bound
這兩個函數的用法與 find 類似,但查找的條件略有不同,時間復雜度\(O(log n)\)
s.lower_bound(x) 查找>=x 的元素中最小的一個,並返回指向該元素的叠代器。
s.upper.bound(x) 查找 >x 的 元 素中最小的一個,並返回指向該元素的叠代器。

erase
設 it 是一個叠代器, s.erase(it) 從 s 中刪除叠代器 it 指向的元素,時間復雜度為\(O(log n)\)
設 x 是一個元素, s.erase(x) 從 s 中刪除所有等於 x 的元素,時間復雜度為\(O(k+logn)\),其中 k 為被刪除的元素個數。
如果想從 multiset 中刪掉至多1個等於 x 的元素,可以執行:

if((it==s.find(x))!=s.end())s.erase(it);

count
s.count(x) 返回集合 s 中等於 x 的元素個數,時間復雜度為\(O(k+logn)\),其中 k 為元素 x 的個數。

//劉汝佳大神的書《算法競賽入門經典》上的例題:

[UVa 10815]Andy‘s First Dictionary 安迪的第一個字典
//想看題目的可以去搜題解,一般題解裏都有題目
//強烈建議不要去UVa ,因為國內FQ太慢了。。。

//此處貼上lrj資源包裏的標程
//據lrj大神的所說,本體沒有太多的技巧,只是為了展示set的用法
//由於string已經定義了“小於”運算符,直接使用set保存單詞集合即可

#include<iostream>
#include<string>
#include<set>
#include<sstream>
using namespace std;

set<string> dict;
string s, buf;

int main() {
  while(cin >> s) {
    for(int i = 0; i < s.length(); i++)
      if(isalpha(s[i])) s[i] = tolower(s[i]); else s[i] = ' ';
    stringstream ss(s);
    while(ss >> buf) dict.insert(buf);
  }
  for(set<string>::iterator it = dict.begin(); it != dict.end(); ++it)
    cout << *it << "\n";
  return 0;
}

C++ STL set(集合)