日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

从零开始学C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)...

發(fā)布時間:2023/12/4 c/c++ 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从零开始学C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、移除性算法 (remove)

?

C++ 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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
? //?TEMPLATE?FUNCTION?remove_copy
template?<? class?_InIt,
????????? class?_OutIt,
????????? class?_Ty?>? inline
_OutIt?_Remove_copy(_InIt?_First,?_InIt?_Last,
????????????????????_OutIt?_Dest,? const?_Ty?&_Val,?_Range_checked_iterator_tag)
{
???? //?copy?omitting?each?matching?_Val
????_DEBUG_RANGE(_First,?_Last);
????_DEBUG_POINTER(_Dest);
???? for?(;?_First?!=?_Last;?++_First)
???????? if?(!(*_First?==?_Val))
????????????*_Dest++?=?*_First;
???? return?(_Dest);
}


template?<? class?_InIt,
????????? class?_OutIt,
????????? class?_Ty?>? inline
_OutIt?unchecked_remove_copy(_InIt?_First,?_InIt?_Last,
?????????????????????????????_OutIt?_Dest,? const?_Ty?&_Val)
{
???? //?copy?omitting?each?matching?_Val
???? return?_STD?_Remove_copy(_CHECKED_BASE(_First),?_CHECKED_BASE(_Last),?_Dest,?_Val,
?????????????????????????????_STD?_Range_checked_iterator_tag());
}


//?TEMPLATE?FUNCTION?remove
template?<? class?_FwdIt,
????????? class?_Ty?>? inline
_FwdIt?remove(_FwdIt?_First,?_FwdIt?_Last,? const?_Ty?&_Val)
{
???? //?remove?each?matching?_Val
????_First?=?find(_First,?_Last,?_Val);
???? if?(_First?==?_Last)
???????? return?(_First);???? //?empty?sequence,?all?done
???? else
????{
???????? //?nonempty?sequence,?worth?doing
????????_FwdIt?_First1?=?_First;
???????? return?(_STDEXT?unchecked_remove_copy(++_First1,?_Last,?_First,?_Val));
????}
}

?

?

如下圖所示:


假設現(xiàn)在想要remove 的元素是3,則傳入到?_Remove_copy 函數(shù)的3個參數(shù)如上圖第一行所示,Val 即3。


接著遍歷First ~ Last 區(qū)間的元素,將非移除元素拷貝到前面,覆蓋前面的元素,最后的指向如圖,函數(shù)返回的是Dest 位置,如下代


碼所示:


for?(;?_First?!=?_Last;?++_First)


?if?(!(*_First?==?_Val))


????????????*_Dest++?=?*_First;


由上圖可看出移除性算法并沒有改變元素的個數(shù),如果要真正刪除,可以將remove 的返回值傳入erase 進行刪除,如:


v.erase(remove(v.begin(), v.end(), 3), v.end()); 即會將后面兩個元素4 和 5 刪除掉。


示例代碼1:

?

C++ 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
25
26
27
28
29
30
? #include?<iostream>
#include?<vector>
#include?<list>
#include?<algorithm>
using? namespace?std;

void?print_element( int?n)
{
????cout?<<?n?<<? '?';
}


int?main( void)
{
???? int?a[]?=?{? 1,? 3,? 2,? 3,? 4,? 5?};
????vector< int>?v(a,?a?+? 6);

????for_each(v.begin(),?v.end(),?print_element);
????cout?<<?endl;

???? /*remove(v.begin(),?v.end(),?3);
????for_each(v.begin(),?v.end(),?print_element);
????cout<<endl;*/


????v.erase(remove(v.begin(),?v.end(),? 3),?v.end());
????for_each(v.begin(),?v.end(),?print_element);
????cout?<<?endl;

???? return? 0;
}

?

?

二、變序性算法(?rotate)

?

C++ Code?
1
2
3
4
5
6
7
? template< class?_FwdIt>? inline
void?rotate(_FwdIt?_First,?_FwdIt?_Mid,?_FwdIt?_Last)
{
???? //?rotate?[_First,?_Last)
???? if?(_First?!=?_Mid?&&?_Mid?!=?_Last)
????????_Rotate(_CHECKED_BASE(_First),?_CHECKED_BASE(_Mid),?_CHECKED_BASE(_Last),?_Iter_cat(_First));
}

?

rotate 調(diào)用了_Rotate,實際上_Rotate 繼續(xù)調(diào)用了某個函數(shù),內(nèi)部實現(xiàn)代碼比較長,而且不容易看懂,這邊可以看一下簡易的等價


版本實現(xiàn),來自這里,如下:

?

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
? template?< class?ForwardIterator>
void?rotate?(ForwardIterator?first,?ForwardIterator?middle,
?????????????ForwardIterator?last)
{
????ForwardIterator?next?=?middle;
???? while?(first?!=?next)
????{
????????swap?(*first++,?*next++);
???????? if?(next?==?last)?next?=?middle;
???????? else? if?(first?==?middle)?middle?=?next;
????}
}

?

?

假設一個容器有 1 2 3 4 5 6 六個元素,現(xiàn)在想把 1 2 放到后面去,可以這樣寫?rotate(v.begin(), v.begin()+2, v.end()); ?如下圖所示:


即將first 與 next 對應的元素互換且不斷向前推進,直到first == next 為止。


三、排序算法 (sort)

?

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
? template< class?_RanIt>? inline
void?sort(_RanIt?_First,?_RanIt?_Last)
{
???? //?order?[_First,?_Last),?using?operator<
????_DEBUG_RANGE(_First,?_Last);
????std::_Sort(_CHECKED_BASE(_First),?_CHECKED_BASE(_Last),?_Last?-?_First);
}

template?<? class?_RanIt,
????????? class?_Pr?>? inline
void?sort(_RanIt?_First,?_RanIt?_Last,?_Pr?_Pred)
{
???? //?order?[_First,?_Last),?using?_Pred
????_DEBUG_RANGE(_First,?_Last);
????_DEBUG_POINTER(_Pred);
????std::_Sort(_CHECKED_BASE(_First),?_CHECKED_BASE(_Last),?_Last?-?_First,?_Pred);
}

?

?

sort 重載了兩個版本,第一個版本只有2個參數(shù),默認按從小到大排序(using?operator<);第二個版本有三個參數(shù),即可以自定義比較邏輯


(_Pred)。它們都調(diào)用了標準庫的std::_Sort, 跟蹤進去發(fā)現(xiàn)比較復雜,在_Sort 內(nèi)會根據(jù)一些條件選擇不同的排序方式,如標準庫的堆排序,合并


序,插入排序等。站在使用的角度看,沒必要去深究,但如果是想學習相關的排序,那是很好的資源。


示例代碼2:

?

C++ 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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
? #include?<iostream>
#include?<vector>
#include?<list>
#include?<algorithm>
using? namespace?std;

void?print_element( int?n)
{
????cout?<<?n?<<? '?';
}

bool?my_greater( int?a,? int?b)
{
???? return?a?>?b;
}

int?main( void)
{
???? int?a[]?=?{? 1,? 2,? 3,? 4,? 5,? 6?};
????vector< int>?v(a,?a?+? 6);

????for_each(v.begin(),?v.end(),?print_element);
????cout?<<?endl;

????rotate(v.begin(),?v.begin()?+? 2,?v.end());
????for_each(v.begin(),?v.end(),?print_element);
????cout?<<?endl;

????sort(v.begin(),?v.end());
????for_each(v.begin(),?v.end(),?print_element);
????cout?<<?endl;

????sort(v.begin(),?v.end(),?my_greater);
????for_each(v.begin(),?v.end(),?print_element);
????cout?<<?endl;

???? return? 0;
}

?

?


四、已序區(qū)間算法 (lower_bound 、upper_bound)


使用這些算法的前提是區(qū)間已經(jīng)是有序的。

?

C++ 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
25
26
27
28
29
30
31
32
33
34
35
36
? //?TEMPLATE?FUNCTION?lower_bound
template?<? class?_FwdIt,
????????? class?_Ty,
????????? class?_Diff?>? inline
_FwdIt?_Lower_bound(_FwdIt?_First,?_FwdIt?_Last,? const?_Ty?&_Val,?_Diff?*)
{
???? //?find?first?element?not?before?_Val,?using?operator<
????_DEBUG_ORDER_SINGLE(_First,?_Last,? true);
????_Diff?_Count?=? 0;
????_Distance(_First,?_Last,?_Count);

???? for?(;? 0?<?_Count;?)
????{
???????? //?divide?and?conquer,?find?half?that?contains?answer
????????_Diff?_Count2?=?_Count?/? 2;
????????_FwdIt?_Mid?=?_First;
????????std::advance(_Mid,?_Count2);
????????_DEBUG_ORDER_SINGLE(_Mid,?_Last,? false);

???????? if?(_DEBUG_LT(*_Mid,?_Val))
????????????_First?=?++_Mid,?_Count?-=?_Count2?+? 1;
???????? else
????????????_Count?=?_Count2;
????}
???? return?(_First);
}

template?<? class?_FwdIt,
????????? class?_Ty?>? inline
_FwdIt?lower_bound(_FwdIt?_First,?_FwdIt?_Last,? const?_Ty?&_Val)
{
???? //?find?first?element?not?before?_Val,?using?operator<
????_ASSIGN_FROM_BASE(_First,
??????????????????????_Lower_bound(_CHECKED_BASE(_First),?_CHECKED_BASE(_Last),?_Val,?_Dist_type(_First)));
???? return?_First;
}

?

?

lower_bound() 返回第一個“大于等于給定值" 的元素位置,其實還重載了另一個low_bound 版本,如下:


?

C++ Code?
1
2
3
4
5
6
7
? //?TEMPLATE?FUNCTION?lower_bound?WITH?PRED
template?<? class?_FwdIt,
????????? class?_Ty,
????????? class?_Diff,
????????? class?_Pr?>? inline
_FwdIt?_Lower_bound(_FwdIt?_First,?_FwdIt?_Last,
???????????????????? const?_Ty?&_Val,?_Pr?_Pred,?_Diff?*)

?

?

也就是可以自定義比較邏輯,需要注意的是如果使用這個版本,那么區(qū)間應該本來就是按comp 方法排序的,如下面這句話:


The elements are compared using?operator<?for the first version, and?comp?for the second. The elements in the range shall already

?be?sorted?according to this same criterion (operator<?or?comp), or at least?partitioned?with respect to?val.


由于是已序區(qū)間,所以函數(shù)內(nèi)用的是二分查找,而兩個版本主要的代碼不同在于:


_DEBUG_LT(*_Mid,?_Val)


_DEBUG_LT_PRED(_Pred, *_Mid, _Val)


upper_bound 與 lower_bound 類似,不過返回的是第一個”大于給定值“ 的元素位置。


示例代碼3:

?

C++ 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
25
26
27
28
29
30
31
32
33
34
35
? #include?<iostream>
#include?<vector>
#include?<list>
#include?<algorithm>
using? namespace?std;

void?print_element( int?n)
{
????cout?<<?n?<<? '?';
}


int?main( void)
{
???? int?a[]?=?{? 1,? 10,? 10,? 14,? 15,? 16?};
????vector< int>?v(a,?a?+? 6);

????for_each(v.begin(),?v.end(),?print_element);
????cout?<<?endl;

????vector< int>::iterator?it;
????it?=?lower_bound(v.begin(),?v.end(),? 10);
???? if?(it?!=?v.end())
????{
????????cout?<<?it?-?v.begin()?<<?endl;
????}

????it?=?upper_bound(v.begin(),?v.end(),? 10);
???? if?(it?!=?v.end())
????{
????????cout?<<?it?-?v.begin()?<<?endl;
????}

???? return? 0;
}

?

?


五、數(shù)值算法(accumulate)


?

C++ 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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
? //?TEMPLATE?FUNCTION?accumulate
template?<? class?_InIt,
????????? class?_Ty?>? inline
_Ty?_Accumulate(_InIt?_First,?_InIt?_Last,?_Ty?_Val)
{
???? //?return?sum?of?_Val?and?all?in?[_First,?_Last)
????_DEBUG_RANGE(_First,?_Last);
???? for?(;?_First?!=?_Last;?++_First)
????????_Val?=?_Val?+?*_First;
???? return?(_Val);
}

template?<? class?_InIt,
????????? class?_Ty?>? inline
_Ty?accumulate(_InIt?_First,?_InIt?_Last,?_Ty?_Val)
{
???? //?return?sum?of?_Val?and?all?in?[_First,?_Last)
???? return?_Accumulate(_CHECKED_BASE(_First),?_CHECKED_BASE(_Last),?_Val);
}

//?TEMPLATE?FUNCTION?accumulate?WITH?BINOP
template?<? class?_InIt,
????????? class?_Ty,
????????? class?_Fn2?>? inline
_Ty?_Accumulate(_InIt?_First,?_InIt?_Last,?_Ty?_Val,?_Fn2?_Func)
{
???? //?return?sum?of?_Val?and?all?in?[_First,?_Last),?using?_Func
????_DEBUG_RANGE(_First,?_Last);
????_DEBUG_POINTER(_Func);
???? for?(;?_First?!=?_Last;?++_First)
????????_Val?=?_Func(_Val,?*_First);
???? return?(_Val);
}

template?<? class?_InIt,
????????? class?_Ty,
????????? class?_Fn2?>? inline
_Ty?accumulate(_InIt?_First,?_InIt?_Last,?_Ty?_Val,?_Fn2?_Func)
{
???? //?return?sum?of?_Val?and?all?in?[_First,?_Last),?using?_Func
???? return?_Accumulate(_CHECKED_BASE(_First),?_CHECKED_BASE(_Last),?_Val,?_Func);
}

?


accumulate 重載了兩個版本,第一個版本實現(xiàn)的是累加,第二個版本帶_Func 參數(shù),可以自定義計算,比如累乘等。代碼都比較好理解,就不贅述


了。看下面的示例代碼4:

?

C++ 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
25
26
27
28
29
30
31
32
33
? #include?<iostream>
#include?<vector>
#include?<list>
#include?<algorithm>
#include?<numeric>
using? namespace?std;

void?print_element( int?n)
{
????cout?<<?n?<<? '?';
}

int?mult( int?a,? int?b)
{
???? return?a?*?b;
}

int?main( void)
{
???? int?a[]?=?{? 1,? 2,? 3,? 4,? 5?};
????vector< int>?v(a,?a?+? 5);

????for_each(v.begin(),?v.end(),?print_element);
????cout?<<?endl;

???? //?累加
????cout?<<?accumulate(v.begin(),?v.end(),? 0)?<<?endl;

???? //?累乘
????cout?<<?accumulate(v.begin(),?v.end(),? 1,?mult)?<<?endl;

???? return? 0;
}

?

?

?

參考:

C++ primer 第四版
Effective C++ 3rd
C++編程規(guī)范


?

總結(jié)

以上是生活随笔為你收集整理的从零开始学C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。