只是一篇超詳細的c++ set用法總結罷了

set是STL中一種標準關聯容器,所謂關聯容器,就是其元素存放位置並不連續,而是按照一定的關係存放的(比如說紅黑樹,哈希表),與此對應的是順序容器,順序容器元素按照順序存放(如vector,list)。

set底層使用平衡的搜索樹——紅黑樹實現。使用時需要包含頭文件<set>。如果大家對紅黑樹瞭解,那麼對set中的規則就很容易理解,如果不瞭解,先記下來也行。set的插入和查找的時間複雜度爲O(logn),且插入之後元素有序排列。set不支持通過迭代器修改元素,因爲如果元素被修改,那麼紅黑樹就可能被打亂。

set在插入數據時會自動對數據進行排序,set中的元素不能重複。

1.成員函數彙總

 以下用set<int>myset來演示用法
//迭代器
(1)myset.begin()//指向myset第一個元素的迭代器
(2)myset.end()//指向myset最後一個元素之後一個位置的迭代器
(3)myset.rbegin()//指向myset最後一個元素的迭代器,注意不等於end()
(4)myset.rend()//指向myset第一個元素之前一個位置的迭代器,注意不等於begin()

//元素調整
(5)myset.insert(4)//向myset裏插入元素4,返回值pair<iterator,bool>,第一位是指向4的迭代器,第二位是否插入成功
(6)myset.insert (const_iterator position, 4);//如果知道4的位置position直接插入效率更高
(7)myset.insert (InputIterator first, InputIterator last);//插入[first,last)的元素
(8)myset.emplace (4)//插入4,返回值pair<iterator,bool>,與insert意義相同
(9)myset.erase(const_iterator position);//刪除position位置元素,返回position
(10)myset.erase (4);//若4之前存在返回1,否則返回0
(11)myset.erase (const_iterator first, const_iterator last);//刪除[first,last)位置元素,返回last
(12)myset.swap(x)//將myset與x中的元素交換,實際上交換的是指針
(13)myset.size()//返回容器中元素個數
(14)myset.clear()//清空myset

//查找計數
(15)myset.find(4)//查找4這個元素,找到返回此元素迭代器,沒有找到返回myset.end()
(16)myset.lower_bound(4)//查找第一個大於等於4的元素,返回此元素迭代器,未找到返回myset.end()
(17)myset.upper_bound(4)//查找第一個大於4的元素,返回此元素迭代器,未找到返回myset.end()
(18)equal_range(4)//返回對組(a,b),a爲myset.lower_bound(4),b爲myset.upper_bound(4)
(19)myset.count(4)//對4進行計數,如果存在返回1,不存在返回0

//容量有關
(20)myset.empty()//如果myset爲空返回true,否則返回false
(21)myset.max_size()//返回容器能容納的最多元素個數,這是容器可以達到的最大潛在大小,但絕不能保證容器能夠達到該大小

//其他
(22)myset.key_comp()//返回容器的比較函數,如果沒有自定義就是默認比較函數(從小到大),比較函數類型爲std::set<int>::key_compare
                    //很少使用,具體用法可參考官方的幫助文檔
(23)myset.value_comp()//同key_comp()

2.構造函數

#include <iostream>
#include <set>

int main ()
{
  int myints[]={ 12,82,37,64,15 };//直接賦值
  std::set<int> first (myints,myints+5);   // 用迭代器賦值
  std::set<int> second;                    // 創建空set

  second = first;                          // set給set賦值
  first = std::set<int>();                 // first爲空

  std::cout << "Size of first: " << int (first.size()) << '\n';
  std::cout << "Size of second: " << int (second.size()) << '\n';
  return 0;
}

輸出:

Size of first: 0
Size of second: 5

3.自定義排序

set默認爲從小到大排序,當我們需要更改排序方式或者我們插入的數據沒有默認排序方式時,我們需要進行自定義排序。

struct cmp {
	bool operator () (const int &a, const int &b) {
		return a > b;//從大到小排序
	}
};

int main()
{
	set<int,cmp>myset = { 2,4,1,4,6 };
	for (auto x : myset)cout << x << " ";//訪問myset中每一個元素
}

輸出爲:6 4 2 1

沒有默認排序方式時的自定義排序,比如set裏面存放的是結構體,那麼如果不自定義排序方式,結構體是無法插入到set中的:

struct st {
	int k;
	string s;
};

struct cmp {
	bool operator () (const st &a, const st &b) {
		return a.k > b.k;
	}
};

int main()
{
	st s,s1,s2;
	s.k = 3;
	s.s = "sss";
	s2.k = 2;
	s2.s = "aaa";
	s1.k = 1;
	s1.s = "bbb";
	set<st, cmp>myset = {s,s1,s2};
	for (auto x : myset)cout << x.k << " " << x.k << endl;
}

輸出:
3 3
2 2
1 1

4.非成員函數重載

1.重載運算符,需要元素類型和比較函數相同。

int main()
{
	std::set<int> foo = { 10,40 };
	std::set<int> bar = { 20,30 };

	// foo ({10,40}) vs bar ({20,30}):
	if (foo == bar) std::cout << "foo and bar are equal\n";
	if (foo != bar) std::cout << "foo and bar are not equal\n";
	if (foo < bar) std::cout << "foo is less than bar\n";
	if (foo > bar) std::cout << "foo is greater than bar\n";
	if (foo <= bar) std::cout << "foo is less than or equal to bar\n";
	if (foo >= bar) std::cout << "foo is greater than or equal to bar\n";

	return 0;
}

輸出:
foo and bar are not equal
foo is less than bar
foo is less than or equal to bar 

2.還有很多STL裏面的通用函數,比如<algorithm>裏面的swap(),upper_bound(),lower_bound()等等,有的在set成員函數裏也有同樣功能的函數,使用哪種都可以。

5.注意事項

1.不能通過set的迭代器改變元素值,畢竟改變值之後紅黑樹就被打亂了。
2.不能通過[ ]的方式訪問元素
3.其迭代器沒有+1,-1的操作,但是有++,--操作,大家可以自己去試一試。
4.set中元素不能重複,與此相對應的multiset中的元素可以重複,multiset和set操作基本一樣。
5.除此之外還有unordered_set和unordered_multiset,爲set和multiset的無序版,使用時要包含頭文件<unordered_set>,其底層爲哈希表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章