STL標準模板庫之set

1、關聯式容器

關聯式容器依據特定的排序準則,自動爲其元素排序。排序準則以函數形式呈現,用來比較元素值(value)或元素鍵(key)。缺省狀況下以operator<進行 比較,不過你也能夠提供本身的比較函數,定義出不一樣的排序準則。數組

一般關聯式容器由二叉樹(binary tree)實現。在二叉樹中,每一個元素(節 點)都有一個父節點和兩個子節點;左子樹的全部元素都比本身小,右子樹的全部元素都比本身大。關聯式容器的差異主要在於元素的類型以及處理重複元素時的方式。數據結構

STL預先定義好的關聯式容器有:集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)。函數

2、什麼是set?

集合(set)簡而言之是一種包含已排序對象的關聯容器,不容許有重複元素。指針

一個集合經過一個鏈表來組織,在插入操做和刪除操做上比向量(vector)快,但查找或添加末尾的元素時會有些慢。具體實現採用了紅黑樹的平衡二叉樹的數據結構。code

特色

  • set中的元素都是排好序的。
  • set中沒有重複的元素。
  • map和set的插入刪除效率比用其餘序列容器高,由於對於關聯容器來講,不須要作內存拷貝和內存移動。

優缺點和適用場景:

優勢:使用平衡二叉樹實現,便於元素查找,且保持了元素的惟一性,以及能自動排序。對象

缺點:每次插入值的時候,都須要調整紅黑樹,效率有必定影響。
適用場景:適用於常常查找一個元素是否在某羣集中且須要排序的場景。排序

3、定義及初始化

set<int> a; //定義一個int類型的集合a
set<int> b(a); //定義並用集合a初始化集合b
set<int> b(a.begin(), a.end()); //將集合a中的全部元素做爲集合b的初始值
//相似的可使用數組來初始化向量:
int n[] = { 1, 2, 3, 4, 5 };
list<int> a(n, n + 5);              //將數組n的前5個元素做爲集合a的初值

4、基本操做

1)容量函數

  • 容器大小:a.size();//返回a中元素個數
  • 容器最大容量:a.max_size();//預分配的內存空間與size不一樣,返回a在內存中總共能夠容納的元素個數
  • 容器判空:a.empty();//空則返回true,不然返回false

2)修改函數

  • 插入函數:a.insert(x);//時間複雜度爲O(log n)內存

    注意:set 在進行插入的時候是不容許有重複的鍵值的,若是新插入的鍵值與原有的鍵值重複,則插入無效(multiset能夠重複)it

  • 刪除函數:a.erase(參數);

    參數能夠是元素或者迭代器,返回下一個元素的迭代器,時間複雜度爲O(log n),注意在multiset中s.erase(x)會刪除全部值爲x的元素

set<int>::iterator it=a.begin();
a.erase(it);
a.erase(3);
  • 刪除區間[first,end)的元素:a.erase(iterator first, iterator end);
  • 清空全部元素:a.clear();
  • 交換兩個同類型容器的元素:a.swap(b);
set<int>st1;
st1.insert(1);
st1.insert(2);
st1.insert(3);
set<int>st2;
st1.insert(4);
st1.insert(5);
st1.insert(6);
st1.swap(st2);
//st1: 4 5 6
//st2: 1 2 3

3)迭代器

  • 開始迭代器指針:a.begin();//時間複雜度爲O(1)

  • 末尾迭代器指針:a.end();

    返回集合的尾迭代器,衆所周知,STL中區間都是左閉右開的,那麼end()函數返回的迭代器即爲指向集合中最大元素的下一個位置的迭代器,所以--s.end()纔是指向集合中最大元素的迭代器,時間複雜度爲O(1)

  • 指向常量的開始迭代器指針:a.cbegin(); //意思就是不能經過這個指針來修改所指的內容,但仍是能夠經過其餘方式修改的,並且指針也是能夠移動的。

  • 指向常量的末尾迭代器指針:a.cend();

  • 反向迭代器指針,指向最後一個元素:a.rbegin();

  • 反向迭代器指針,指向第一個元素的前一個元素:a.rend();

  • 返回最後一個key<=keyElem元素的迭代器:a.lower_bound(keyElem);

  • 返回第一個key>keyElem元素的迭代器:a.upper_bound(keyElem);

//假設 st:1 2 3
    cout << "*(st.begin()): " << *(st.begin()) << endl;
    cout << "*(st.end()): " << *(--st.end()) << endl;
    cout << "*(st.cbegin()): " << *(st.cbegin()) << endl;
    cout << "*(st.cend()): " << *(--st.cend()) << endl;
    cout << "*(st.rbegin()): " << *(st.rbegin()) << endl;
    cout << "*(st.rend()): " << *(--st.rend()) << endl;
    cout << "*(st.lower_bound(2)): " << *(st.lower_bound(2)) << endl;
    cout << "*(st.upper_bound(2)): " << *(st.upper_bound(2)) << endl;
/*
*(st.begin()): 1
*(st.end()): 3
*(st.cbegin()): 1
*(st.cend()): 3
*(st.rbegin()): 3
*(st.rend()): 1
*(st.lower_bound(2)): 2
*(st.upper_bound(2)): 3
*/

4)其餘函數

  • 統計鍵key的元素個數:a.count(key);//有則爲1,無則爲0

  • 查找函數:a.find(x);

    在set中查找值爲x的元素,並返回指向該元素的迭代器,若不存在,返回set.end(),時間複雜度爲O(log n)

5、與序列容器的不一樣點

  • set 只支持默認構造函數和拷貝構造函數,沒有其它重載的構造函數。
  • set 只能使用insert的兩種重載函數插入,不支持push_back()和push_front()函數。
  • set 能不經過迭代器,只經過元素值來刪除該元素。
  • set 容器不提供下標操做符。爲了經過鍵從 set 中獲取元素,可以使用 find 運算。
  • set 不支持STL裏的reverse和sort算法。
相關文章
相關標籤/搜索