1、set和multiset基礎css
set和multiset會根據特定的排序準則,自動將元素進行排序。不一樣的是後者容許元素重複而前者不容許。html
須要包含頭文件:java
#include <set>ios
set和multiset都是定義在std空間裏的類模板:less
所謂排序準則,必須定義strict weak ordering,其意義以下:ide
一、必須使反對稱的。svg
對operator<而言,若是x<y爲真,則y<x爲假。函數
二、必須使可傳遞的。性能
對operator<而言,若是x<y爲真,且y<z爲真,則x<z爲真。ui
三、必須是非自反的。
對operator<而言,x<x永遠爲假。
由於上面的這些特性,排序準則能夠用於相等性檢驗,就是說,若是兩個元素都不小於對方,則它們相等。
2、set和multiset的功能
和全部關聯式容器相似,一般使用平衡二叉樹完成。事實上,set和multiset一般以紅黑樹實做而成。
自動排序的優勢是使得搜尋元素時具備良好的性能,具備對數時間複雜度。可是形成的一個缺點就是:
不能直接改變元素值。由於這樣會打亂原有的順序。
改變元素值的方法是:先刪除舊元素,再插入新元素。
存取元素只能經過迭代器,從迭代器的角度看,元素值是常數。
3、操做函數
構造函數和析構函數
set的形式能夠是:
有兩種方式能夠定義排序準則:
一、以template參數定義:
此時,排序準則就是型別的一部分。型別系統確保只有排序準則相同的容器才能被合併。
程序實例:
程序運行會報錯。可是若是把s1的排序準則也指定爲greater<int>便運行成功。
二、以構造函數參數定義。
這種狀況下,同一個型別能夠運用不一樣的排序準則,而排序準則的初始值或狀態也能夠不一樣。若是執行期纔得到排序準則,並且須要用到不一樣的排序準則,這種方式能夠派上用場。
程序實例:
運行結果:
非變更性操做
注意:元素比較操做只能用於型別相同的容器。
特殊的搜尋函數
賦值
賦值操做兩端的容器必須具備相同的型別,可是比較準則自己能夠不一樣,可是其型別必須相同。若是比較準則的不一樣,準則自己也會被賦值或交換。
迭代器相關函數
元素的插入和刪除
注意:插入函數的返回值不徹底相同。
set提供的插入函數:
multiset提供的插入函數:
返回值型別不一樣的緣由是set不容許元素重複,而multiset容許。當插入的元素在set中已經包含有一樣值的元素時,插入就會失敗。因此set的返回值型別是由pair組織起來的兩個值:
第一個元素返回新元素的位置,或返回現存的同值元素的位置。第二個元素表示插入是否成功。
set的第二個insert函數,若是插入失敗,就只返回重複元素的位置!
可是,全部擁有位置提示參數的插入函數的返回值型別是相同的。這樣就確保了至少有了一個通用型的插入函數,在各類容器中有共通接口。
注意:還有一個返回值不一樣的狀況是:做用於序列式容器和關聯式容器的erase()函數:
序列式容器的erase()函數:
關聯式容器的erase()函數:
這徹底是爲了性能的考慮。由於關聯式容器都是由二叉樹實現,搜尋某元素並返回後繼元素可能很費時。
注意:s1和s2有不一樣的排序準則,因此他們的型別不一樣,不能直接進行相互賦值或比較。
運行結果:
Defined in header
<iterator>
|
||
(1) | ||
template< class C > auto rbegin( C& c ) -> decltype(c.rbegin()); |
(since C++14) (until C++17) |
|
template< class C > constexpr auto rbegin( C& c ) -> decltype(c.rbegin()); |
(since C++17) | |
(1) | ||
template< class C > auto rbegin( const C& c ) -> decltype(c.rbegin()); |
(since C++14) (until C++17) |
|
template< class C > constexpr auto rbegin( const C& c ) -> decltype(c.rbegin()); |
(since C++17) | |
(2) | ||
template< class T, size_t N > reverse_iterator<T*> rbegin( T (&array)[N] ); |
(since C++14) (until C++17) |
|
template< class T, size_t N > constexpr reverse_iterator<T*> rbegin( T (&array)[N] ); |
(since C++17) | |
(3) | ||
template< class C > auto crbegin( const C& c ) -> decltype(std::rbegin(c)); |
(since C++14) (until C++17) |
|
template< class C > constexpr auto crbegin( const C& c ) -> decltype(std::rbegin(c)); |
(since C++17) | |
Returns an iterator to the reverse-beginning of the given container c
or array array
.
c
.
c
.
c | - | a container with a rbegin method |
array | - | an array of arbitrary type |
An iterator to the reverse-beginning of c
or array
In addition to being included in <iterator>
, std::rbegin
and std::crbegin
are guaranteed to become available if any of the following headers are included: <array>
, <deque>
, <forward_list>
, <list>
, <map>
, <regex>
, <set>
, <string>
, <string_view> (since C++17), <unordered_map>
, <unordered_set>
, and <vector>
.
Custom overloads of rbegin
may be provided for classes that do not expose a suitable rbegin()
member function, yet can be iterated. The following overload is already provided by the standard library:
(C++14)
|
specializes std::rbegin (function) |
#include <iostream>#include <vector>#include <iterator>int main ( ){auto vi = std :: rbegin ( v ) ;int a [ ] = { - 5 , 10 , 15 } ;auto ai = std :: rbegin ( a ) ;}
Output:
415
因此這篇博客就是想羅列一下C++11對vector容器的擴充。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<code
class
=
"hljs cpp"
>#include <iostream>
#include <vector>
int
main ()
{
std::vector<
int
> myvector = {
10
,
20
,
30
,
40
,
50
};
std::cout <<
"myvector contains:"
;
for
(auto it = myvector.cbegin(); it != myvector.cend(); ++it)
std::cout <<
' '
<< *it;
std::cout <<
'\n'
;
return
0
;
}
Output:
myvector contains:
10
20
30
40
50
</
int
></vector></iostream></code>
|
如何使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<code
class
=
"hljs cpp"
>#include <iostream>
#include <vector>
int
main ()
{
std::vector<
int
> myvector = {
10
,
20
,
30
};
auto it = myvector.emplace ( myvector.begin()+
1
,
100
);
myvector.emplace ( it,
200
);
myvector.emplace ( myvector.end(),
300
);
std::cout <<
"myvector contains:"
;
for
(auto& x: myvector)
std::cout <<
' '
<< x;
std::cout <<
'\n'
;
return
0
;
}
Output:
myvector contains:
10
200
100
20
30
300
</
int
></vector></iostream></code>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<code
class
=
"hljs cpp"
>#include <iostream>
#include <vector>
int
main ()
{
std::vector<
int
> myvector (
5
);
int
* p = myvector.data();
*p =
10
;
++p;
*p =
20
;
p[
2
] =
100
;
std::cout <<
"myvector contains:"
;
for
(unsigned i=
0
; i<myvector.size(); ++i)=
""
std::cout=
""
<<=
""
'="" myvector[i];="" '
\n';=
""
return
=
""
0
;=
""
}=
""
output:=
""
myvector=
""
contains:=
""
10
=
""
20
=
""
0
=
""
100
=
""
0
</
int
></vector></iostream></code>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<code
class
=
"hljs cpp"
><code
class
=
"hljs cpp"
>#include <iostream>
#include <vector>
int
main ()
{
std::vector<
int
> myvector (
100
);
std::cout <<
"1. capacity of myvector: "
<< myvector.capacity() <<
'\n'
;
std::cout <<
"1. size of myvector: "
<< myvector.size() <<
'\n'
;
myvector.resize(
10
);
std::cout <<
"2. capacity of myvector: "
<< myvector.capacity() <<
'\n'
;
std::cout <<
"2. size of myvector: "
<< myvector.size() <<
'\n'
;
myvector.shrink_to_fit();
std::cout <<
"3. capacity of myvector: "
<< myvector.capacity() <<
'\n'
;
std::cout <<
"3. size of myvector: "
<< myvector.size() <<
'\n'
;
return
0
;
}
//輸出
1
. capacity of myvector:
100
1
. size of myvector:
100
2
. capacity of myvector:
100
2
. size of myvector:
10
3
. capacity of myvector:
10
3
. size of myvector:
10
</
int
></vector></iostream></code></code>
|
此時,就是要明白size和capacity的區別,也就會更加理解resize和reserve的區別了!