一、移除性算法 (remove)
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br>
8<br>
9<br>
10<br>
11<br>
12<br>
13<br>
14<br>
15<br>
16<br>
17<br>
18<br>
19<br>
20<br>
21<br>
22<br>
23<br>
24<br>
25<br>
26<br>
27<br>
28<br>
29<br>
30<br>
31<br>
32<br>
33<br>
34<br>
35<br>
36<br>
37<br>
38<br>
39<br>
40<br>
41<br>
42<br>
43<br>
44<br>
45<br></nobr>
|
|
//TEMPLATEFUNCTIONremove_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)
{ //copyomittingeachmatching_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
_OutItunchecked_remove_copy(_InIt_First,_InIt_Last,
_OutIt_Dest,const_Ty&_Val)
{ //copyomittingeachmatching_Val return_STD_Remove_copy(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,_Val,
_STD_Range_checked_iterator_tag());
}
//TEMPLATEFUNCTIONremove template<class_FwdIt, class_Ty>inline
_FwdItremove(_FwdIt_First,_FwdIt_Last,const_Ty&_Val)
{ //removeeachmatching_Val _First=find(_First,_Last,_Val); if(_First==_Last) return(_First);//emptysequence,alldone else
{ //nonemptysequence,worthdoing _FwdIt_First1=_First; return(_STDEXTunchecked_remove_copy(++_First1,_Last,_First,_Val));
}
}
|
如下图所示:
假设现在想要remove 的元素是3,则传入到_Remove_copy 函数的3个参数如上图第一行所示,Val 即3。
接着遍历First ~ Last 区间的元素,将非移除元素拷贝到前面,覆盖前面的元素,最后的指向如图,函数返回的是Dest 位置,如下代
码所示:
for(;_First!=_Last;++_First)
if(!(*_First==_Val))
*_Dest++=*_First;
由上图可看出移除性算法并没有改变元素的个数,如果要真正删除,可以将remove 的返回值传入erase 进行删除,如:
v.erase(remove(v.begin(), v.end(), 3), v.end()); 即会将后面两个元素4 和 5 删除掉。
在这里顺便提一下,erase 会使当前迭代器失效,但可以返回下一个迭代器,故如果需要在遍历中删除,下面的做法才是正确的:
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br>
8<br>
9<br>
10<br>
11<br>
12<br>
13<br>
14<br>
15<br>
16<br>
17<br>
18<br>
19<br>
20<br>
21<br>
22<br>
23<br>
24<br>
25<br>
26<br>
27<br>
28<br>
29<br>
30<br>
31<br>
32<br></nobr>
|
|
#include<iostream> #include<vector>
usingnamespacestd;
intmain(void)
{ inta[]={3,1,2,3,4};
vector<int>v(a,a+5);
//for(vector<int>::iteratorit=v.begin();it!=v.end();++it) //{ //if(*it==3) //v.erase(it);ERROR! //else //cout<<*it<<''; //}
for(vector<int>::iteratorit=v.begin();it!=v.end();)
{ if(*it==3)
it=v.erase(it); else
{
cout<<*it<<'';
++it;
}
}
cout<<endl; return0;
}
|
示例代码1:
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br>
8<br>
9<br>
10<br>
11<br>
12<br>
13<br>
14<br>
15<br>
16<br>
17<br>
18<br>
19<br>
20<br>
21<br>
22<br>
23<br>
24<br>
25<br>
26<br>
27<br>
28<br>
29<br>
30<br></nobr>
|
|
#include<iostream> #include<vector> #include<list> #include<algorithm> usingnamespacestd;
voidprint_element(intn)
{
cout<<n<<'';
}
intmain(void)
{ inta[]={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;
return0;
}
|
二、变序性算法(rotate)
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br></nobr>
|
|
template<class_FwdIt>inline voidrotate(_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 调用了_Rotate,实际上_Rotate 继续调用了某个函数,内部实现代码比较长,而且不容易看懂,这边可以看一下简易的等价
版本实现,来自这里,如下:
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br>
8<br>
9<br>
10<br>
11<br>
12<br></nobr>
|
|
template<classForwardIterator> voidrotate(ForwardIteratorfirst,ForwardIteratormiddle,
ForwardIteratorlast)
{
ForwardIteratornext=middle; while(first!=next)
{
swap(*first++,*next++); if(next==last)next=middle; elseif(first==middle)middle=next;
}
}
|
假设一个容器有 1 2 3 4 5 6 六个元素,现在想把 1 2 放到后面去,可以这样写rotate(v.begin(), v.begin()+2, v.end()); 如下图所示:
即将first 与 next 对应的元素互换且不断向前推进,直到first == next 为止。
三、排序算法 (sort)
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br>
8<br>
9<br>
10<br>
11<br>
12<br>
13<br>
14<br>
15<br>
16<br>
17<br></nobr>
|
|
template<class_RanIt>inline voidsort(_RanIt_First,_RanIt_Last)
{ //order[_First,_Last),usingoperator< _DEBUG_RANGE(_First,_Last);
std::_Sort(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Last-_First);
}
template<class_RanIt, class_Pr>inline voidsort(_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个参数,默认按从小到大排序(usingoperator<)
;第二个版本有三个参数,即可以自定义比较逻辑
(_Pred)。它们都调用了标准库的std::_Sort, 跟踪进去发现比较复杂,在_Sort 内会根据一些条件选择不同的排序方式,如标准库的堆排序,合并
排序,插入排序等等。站在使用的角度看,没必要去深究,但如果是想学习相关的排序,那是很好的资源。
示例代码2:
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br>
8<br>
9<br>
10<br>
11<br>
12<br>
13<br>
14<br>
15<br>
16<br>
17<br>
18<br>
19<br>
20<br>
21<br>
22<br>
23<br>
24<br>
25<br>
26<br>
27<br>
28<br>
29<br>
30<br>
31<br>
32<br>
33<br>
34<br>
35<br>
36<br>
37<br>
38<br></nobr>
|
|
#include<iostream> #include<vector> #include<list> #include<algorithm> usingnamespacestd;
voidprint_element(intn)
{
cout<<n<<'';
}
boolmy_greater(inta,intb)
{ returna>b;
}
intmain(void)
{ inta[]={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;
return0;
}
|
四、已序区间算法 (lower_bound 、upper_bound)
使用这些算法的前提是区间已经是有序的。
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br>
8<br>
9<br>
10<br>
11<br>
12<br>
13<br>
14<br>
15<br>
16<br>
17<br>
18<br>
19<br>
20<br>
21<br>
22<br>
23<br>
24<br>
25<br>
26<br>
27<br>
28<br>
29<br>
30<br>
31<br>
32<br>
33<br>
34<br>
35<br>
36<br></nobr>
|
|
//TEMPLATEFUNCTIONlower_bound template<class_FwdIt, class_Ty, class_Diff>inline
_FwdIt_Lower_bound(_FwdIt_First,_FwdIt_Last,const_Ty&_Val,_Diff*)
{ //findfirstelementnotbefore_Val,usingoperator< _DEBUG_ORDER_SINGLE(_First,_Last,true);
_Diff_Count=0;
_Distance(_First,_Last,_Count);
for(;0<_Count;)
{ //divideandconquer,findhalfthatcontainsanswer _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
_FwdItlower_bound(_FwdIt_First,_FwdIt_Last,const_Ty&_Val)
{ //findfirstelementnotbefore_Val,usingoperator< _ASSIGN_FROM_BASE(_First,
_Lower_bound(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Val,_Dist_type(_First))); return_First;
}
|
lower_bound() 返回第一个“大于等于给定值" 的元素位置,其实还重载了另一个low_bound 版本,如下:
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br></nobr>
|
|
//TEMPLATEFUNCTIONlower_boundWITHPRED template<class_FwdIt, class_Ty, class_Diff, class_Pr>inline
_FwdIt_Lower_bound(_FwdIt_First,_FwdIt_Last, const_Ty&_Val,_Pr_Pred,_Diff*)
|
也就是可以自定义比较逻辑,需要注意的是如果使用这个版本,那么区间应该本来就是按comp 方法排序的,如下面这句话:
The elements are compared usingoperator<
for the first version, andcompfor
the second. The elements in the range shall already
besortedaccording
to this same criterion (operator<
orcomp),
or at leastpartitionedwith respect
toval.
由于是已序区间,所以函数内用的是二分查找,而两个版本主要的代码不同在于:
_DEBUG_LT(*_Mid,_Val)
_DEBUG_LT_PRED(_Pred, *_Mid, _Val)
upper_bound 与 lower_bound 类似,不过返回的是第一个”大于给定值“ 的元素位置。
示例代码3:
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br>
8<br>
9<br>
10<br>
11<br>
12<br>
13<br>
14<br>
15<br>
16<br>
17<br>
18<br>
19<br>
20<br>
21<br>
22<br>
23<br>
24<br>
25<br>
26<br>
27<br>
28<br>
29<br>
30<br>
31<br>
32<br>
33<br>
34<br>
35<br></nobr>
|
|
#include<iostream> #include<vector> #include<list> #include<algorithm> usingnamespacestd;
voidprint_element(intn)
{
cout<<n<<'';
}
intmain(void)
{ inta[]={1,10,10,14,15,16};
vector<int>v(a,a+6);
for_each(v.begin(),v.end(),print_element);
cout<<endl;
vector<int>::iteratorit;
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;
}
return0;
}
|
五、数值算法(accumulate)
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br>
8<br>
9<br>
10<br>
11<br>
12<br>
13<br>
14<br>
15<br>
16<br>
17<br>
18<br>
19<br>
20<br>
21<br>
22<br>
23<br>
24<br>
25<br>
26<br>
27<br>
28<br>
29<br>
30<br>
31<br>
32<br>
33<br>
34<br>
35<br>
36<br>
37<br>
38<br>
39<br>
40<br>
41<br>
42<br></nobr>
|
|
//TEMPLATEFUNCTIONaccumulate template<class_InIt, class_Ty>inline
_Ty_Accumulate(_InIt_First,_InIt_Last,_Ty_Val)
{ //returnsumof_Valandallin[_First,_Last) _DEBUG_RANGE(_First,_Last); for(;_First!=_Last;++_First)
_Val=_Val+*_First; return(_Val);
}
template<class_InIt, class_Ty>inline
_Tyaccumulate(_InIt_First,_InIt_Last,_Ty_Val)
{ //returnsumof_Valandallin[_First,_Last) return_Accumulate(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Val);
}
//TEMPLATEFUNCTIONaccumulateWITHBINOP template<class_InIt, class_Ty, class_Fn2>inline
_Ty_Accumulate(_InIt_First,_InIt_Last,_Ty_Val,_Fn2_Func)
{ //returnsumof_Valandallin[_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
_Tyaccumulate(_InIt_First,_InIt_Last,_Ty_Val,_Fn2_Func)
{ //returnsumof_Valandallin[_First,_Last),using_Func return_Accumulate(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Val,_Func);
}
|
accumulate 重载了两个版本,第一个版本实现的是累加,第二个版本带_Func 参数,可以自定义计算,比如累乘等。代码都比较好理解,就不赘述
了。看下面的示例代码4:
C++ Code
<nobr>1<br>
2<br>
3<br>
4<br>
5<br>
6<br>
7<br>
8<br>
9<br>
10<br>
11<br>
12<br>
13<br>
14<br>
15<br>
16<br>
17<br>
18<br>
19<br>
20<br>
21<br>
22<br>
23<br>
24<br>
25<br>
26<br>
27<br>
28<br>
29<br>
30<br>
31<br>
32<br>
33<br></nobr>
|
|
#include<iostream> #include<vector> #include<list> #include<algorithm> #include<numeric> usingnamespacestd;
voidprint_element(intn)
{
cout<<n<<'';
}
intmult(inta,intb)
{ returna*b;
}
intmain(void)
{ inta[]={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;
return0;
}
|
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范
分享到:
相关推荐
余文溪的《C++ STL--数据结构与算法实现》这本书很可能详细介绍了如何利用STL来解决实际问题,并通过示例程序代码来加深理解。 STL中的核心概念有以下几个: 1. 容器(Containers):这是STL的基础,它们是存储...
C++ STL 中提供了多种查找算法,每种算法都有其特点和使用场景,本文将对这些算法进行详细的介绍和比较。 首先,需要注意的是,STL 中的查找算法可以分为两组:A 组和 B 组。A 组包括 count 和 find,这两种算法不...
在给定的压缩包文件“lower_bound函数代码(C++实现).rar”中,可能包含了一个示例文档`.docx`,该文档可能详细解释了如何使用`lower_bound`函数,并提供了相关的代码实现和示例。通常,`lower_bound`的实现会基于...
在C++编程中,库函数和STL(Standard Template Library,标准模板库)是不可或缺的组成部分,它们极大地提升了代码的效率和可读性。本文将深入探讨C++库函数和STL算法,以及如何在实际编程中应用这些概念。 首先,...
虽然 C++ STL 没有提供 `lower_bound()` 函数的具体实现代码,但从其实现原理上来看,该函数采用了二分查找法来进行高效的查找。二分查找的时间复杂度为 O(log n),这意味着即使面对大规模数据集,该函数也能保持...
- **查找算法**:`find()`, `find_if()`, `lower_bound()`, `upper_bound()`等,用于在容器中查找特定元素或满足条件的元素。 - **交换和复制算法**:`swap()`, `copy()`等,用于元素的交换和容器之间的复制。 - ...
`lower_bound` 是 C++ STL 中非常重要的一个函数,它提供了一种高效的方式来定位有序序列中的元素。通过选择合适的版本和参数配置,可以灵活地满足不同的应用需求。无论是对于初学者还是资深开发者而言,掌握 `lower...
STL,全称为Standard Template Library(标准模板库),是C++编程语言中不可或缺的一部分,它为程序员提供了高效且可重用的数据结构和算法。STL的主要组成部分包括容器、迭代器、算法和函数对象,这些组件共同构成了...
lower_bound函数
- 使用sort和lower_bound、upper_bound实现排序和二分查找。 - 利用函数对象自定义比较逻辑,如在排序中使用greater替代默认的less。 通过深入阅读书籍和实践代码,你可以掌握STL的精髓,提升编程效率,写出更高效...
SGI STL,全称为Stanford Graphics Group Standard Template Library,是由斯坦福大学图形小组开发的一套C++标准模板库,后来成为C++标准库的一部分。它为C++程序员提供了丰富的容器、迭代器、算法和函数对象,极大...
《从零开始学C++》是一份专为初学者设计的教学资料,旨在引导学习者逐步掌握C++编程语言。这份教程包含丰富的基础知识讲解,搭配教案和源代码,使得学习过程更具实践性和互动性。 首先,从C++的基础部分开始,学习...
理解并熟练使用STL是C++程序员必备的技能之一,它能帮助编写出高效、可读性强的代码。在面试中,对STL的深入理解不仅可以展示你的技术实力,还能表现出你对编程最佳实践的追求。因此,熟悉STL的各个部分并能够灵活...
探讨了C++标准模板库(STL)的核心组件和使用技巧,帮助读者深入理解如何高效地利用STL进行数据结构与算法的实现。文章首先介绍了STL的设计理念和核心组成部分,包括容器、迭代器、算法和函数对象。接着,逐一分析了...
`lower_bound`经常与其他算法一起使用,比如`binary_search`等,以实现更高效的操作。例如,在一个排序的容器中快速查找一个元素是否存在: ```cpp bool exists = std::binary_search(v.begin(), v.end(), "cherry...
"C++_STL使用例子大全"可能会包含许多实际应用STL的实例,这些例子有助于理解STL在不同场景下的使用方式,例如如何使用vector来动态管理数组,如何使用map来建立关联关系,以及如何使用算法如sort进行排序操作。...
STL(Standard Template Library,标准模板库)是C++编程语言中的一个重要...结合备忘单和示例代码,开发者能更直观地理解每种算法的工作原理和应用场景。对于C++程序员来说,深入掌握STL是提高编程能力的关键一步。
第5章 C++ STL泛化技术分析 58 5.1 算法和迭代器 58 5.1.1 算法 58 5.1.2 迭代器 61 5.1.3 函数对象 65 5.1.4 适配器 68 5.2 内存分配器和容器 74 5.2.1 内存分配器 75 5.2.2 容器 77 5.3 概念 ...
C++ STL(Standard Template Library,标准模板库)是C++编程中极其重要的组成部分,它提供了一组高效且灵活的算法,用于处理各种数据结构,如向量、列表、集合等。这些算法通常与容器(如vector、list)配合使用,...