`
aspnetwinform
  • 浏览: 89824 次
  • 性别: Icon_minigender_2
  • 来自: 武汉
社区版块
存档分类
最新评论

从零开始学C++之STL(六):变动性算法源代码分析与使用示例(copy_backward、 transform、 replace_copy_if 等)

 
阅读更多

首先回顾前面的文章,我们把for_each 归类为非变动性算法,实际上它也可以算是变动性算法,取决于传入的第三个参数,即函数

针。如果在函数内对容器元素做了修改,那么就属于变动性算法。


变动性算法源代码分析与使用示例:


一、copy、copy_backward

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></nobr>
//TEMPLATEFUNCTIONcopy
template<class_InIt,class_OutIt,class_InOutItCat>
inline
_OutIt__CLRCALL_OR_CDECL_Copy_opt(_InIt_First,_InIt_Last,_OutIt_Dest,
_InOutItCat,_Nonscalar_ptr_iterator_tag,_Range_checked_iterator_tag)
{
//copy[_First,_Last)to[_Dest,...),arbitraryiterators
_DEBUG_RANGE(_First,_Last);
for(;_First!=_Last;++_Dest,++_First)
*_Dest=*_First;
return(_Dest);
}

template<class_InIt,class_OutIt>
inline
_IF_CHK(_OutIt)__CLRCALL_OR_CDECLcopy(_InIt_First,_InIt_Last,_OutIt_Dest)
{
//copy[_First,_Last)to[_Dest,...)
return(_Copy_opt(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,
_Iter_random(_First,_Dest),_Ptr_cat(_First,_Dest),_Range_checked_iterator_tag()));
}

//TEMPLATEFUNCTIONcopy_backward
template<class_BidIt1,class_BidIt2,class_InOutItCat>
inline
_BidIt2__CLRCALL_OR_CDECL_Copy_backward_opt(_BidIt1_First,_BidIt1_Last,_BidIt2_Dest,
_InOutItCat,_Nonscalar_ptr_iterator_tag,_Range_checked_iterator_tag)
{
//copy[_First,_Last)backwardsto[...,_Dest),arbitraryiterators
_DEBUG_RANGE(_First,_Last);
while(_First!=_Last)
*--_Dest=*--_Last;
return(_Dest);
}

template<class_BidIt1,
class_BidIt2>inline
_IF_CHK(_BidIt2)__CLRCALL_OR_CDECLcopy_backward(_BidIt1_First,_BidIt1_Last,_BidIt2_Dest)
{
//copy[_First,_Last)backwardsto[...,_Dest)
return_Copy_backward_opt(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,
_Iter_random(_First,_Dest),_Ptr_cat(_First,_Dest),_STD_Range_checked_iterator_tag());
}

copy 调用了_Copy_opt,在此函数内递增迭代器,从前两个参数指定的区间内取出元素并拷贝到对应_Dest位置上。


for(;_First!=_Last;++_Dest,++_First)


*_Dest=*_First;


copy_backward 调用了_Copy_backward_opt,与copy 不同的是实现反向拷贝,即从尾端开始拷贝,所以是递减迭代器。


while(_First!=_Last)


*--_Dest=*--_Last;


示例代码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> 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></nobr>
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
usingnamespacestd;

voidprint_element(intn)
{
cout<<n<<'';
}

voidadd_3(int&n)
{
n+=3;
}

intmain(void)
{
inta[]={1,2,3,4,5};
vector<int>v(a,a+5);
list<int>l(15);

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

for_each(v.begin(),v.end(),add_3);

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

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

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

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

return0;
}



二、transfrom

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> 46<br> 47<br> 48<br> 49<br> 50<br> 51<br> 52<br> 53<br> 54<br> 55<br> 56<br> 57<br> 58<br> 59<br> 60<br> 61<br> 62<br> 63<br> 64<br> 65<br> 66<br> 67<br> 68<br> 69<br> 70<br></nobr>

//TEMPLATEFUNCTIONtransformWITHUNARYOP
template<class_InIt,class_OutIt,class_Fn1,class_InOutItCat>
inline
_OutIt_Transform(_InIt_First,_InIt_Last,_OutIt_Dest,_Fn1_Func,
_InOutItCat,_Range_checked_iterator_tag)
{
//transform[_First,_Last)with_Func
_DEBUG_RANGE(_First,_Last);
_DEBUG_POINTER(_Dest);
_DEBUG_POINTER(_Func);
for(;_First!=_Last;++_First,++_Dest)
*_Dest=_Func(*_First);
return(_Dest);
}

template<class_InIt,class_OutIt,class_Fn1>
inline
_IF_CHK(_OutIt)transform(_InIt_First,_InIt_Last,_OutIt_Dest,_Fn1_Func)
{
return_Transform(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,_Func,
_Iter_random(_First,_Dest),_STD_Range_checked_iterator_tag());
}


//TEMPLATEFUNCTIONtransformWITHBINARYOP
template<class_InIt1,class_InIt2,class_OutIt,class_Fn2,class_InItCats,class_InOutItCat>
inline
_OutIt_Transform(_InIt1_First1,_InIt1_Last1,_InIt2_First2,
_OutIt_Dest,_Fn2_Func,
_InItCats,_InOutItCat,
_Range_checked_iterator_tag,_Range_checked_iterator_tag)
{
//transform[_First1,_Last1)and[_First2,_Last2)with_Func
_DEBUG_RANGE(_First1,_Last1);
_DEBUG_POINTER(_Dest);
_DEBUG_POINTER(_Func);
for(;_First1!=_Last1;++_First1,++_First2,++_Dest)
*_Dest=_Func(*_First1,*_First2);
return(_Dest);
}


template<class_InIt1,class_InIt2,class_OutIt,class_Fn2,class_InOutItCat>
inline
_OutIt_Transform(_InIt1_First1,_InIt1_Last1,_InIt2_First2,
_OutIt_Dest,_Fn2_Func,
random_access_iterator_tag,_InOutItCat,
_Range_checked_iterator_tag,_Range_checked_iterator_tag)
{
//transform[_First1,_Last1)and[_First2,_Last2)with_Func
//forrangecheckediterators,thiswillmakesurethereisenoughspace
_InIt2_Last2=_First2+(_Last1-_First1);
(_Last2);
return_Transform(_First1,_Last1,_CHECKED_BASE(_First2),
_Dest,_Func,
forward_iterator_tag(),forward_iterator_tag(),
_Range_checked_iterator_tag(),_Range_checked_iterator_tag());
}


template<class_InIt1,class_InIt2,class_OutIt,class_Fn2>
inline
_IF_CHK2_(_InIt2,_OutIt,_OutIt)transform(_InIt1_First1,_InIt1_Last1,_InIt2_First2,
_OutIt_Dest,_Fn2_Func)
{
return_Transform(_CHECKED_BASE(_First1),_CHECKED_BASE(_Last1),_First2,_Dest,_Func,
_Iter_random(_First1,_First2),_Iter_random(_First1,_Dest),
_STD_Range_checked_iterator_tag(),_STD_Range_checked_iterator_tag());
}

实际上transfrom 重载了两个版本,一个是四个参数的,即将前两个参数指定区间内的元素执行某种操作(函数内)后拷贝到第三个


参数指示的区间上。而另一个版本是五个参数的,即将两个区间的对应元素进行某种操作后拷贝到第三个区间上去。核心的代码区


别在于下面两行:


*_Dest = _Func(*_First);


*_Dest = _Func(*_First1, *_First2);


示例代码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> 39<br></nobr>
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
usingnamespacestd;

voidprint_element(intn)
{
cout<<n<<'';
}

intfun(inta)
{
return2*a;
}

intfun2(inta,intb)
{
returna+b;
}

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

list<int>l(5);
list<int>ll(2);

transform(v.begin(),v.end(),l.begin(),fun);
for_each(l.begin(),l.end(),print_element);
cout<<endl;

transform(v.begin(),v.begin()+2,v.begin()+3,ll.begin(),fun2);
for_each(ll.begin(),ll.end(),print_element);
cout<<endl;

return0;
}

输出为 :

2 4 6 8 10

5 7


三、replace、replace_copy、replace_copy_if

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> 46<br> 47<br> 48<br> 49<br> 50<br> 51<br> 52<br> 53<br> 54<br> 55<br> 56<br> 57<br> 58<br> 59<br> 60<br> 61<br> 62<br> 63<br> 64<br> 65<br> 66<br> 67<br> 68<br> 69<br> 70<br> 71<br> 72<br> 73<br> 74<br> 75<br> 76<br> 77<br> 78<br> 79<br></nobr>

//TEMPLATEFUNCTIONreplace
template<class_FwdIt,
class_Ty>inline
void_Replace(_FwdIt_First,_FwdIt_Last,
const_Ty&_Oldval,const_Ty&_Newval)
{
//replaceeachmatching_Oldvalwith_Newval
_DEBUG_RANGE(_First,_Last);
for(;_First!=_Last;++_First)
if(*_First==_Oldval)
*_First=_Newval;
}

template<class_FwdIt,
class_Ty>inline
voidreplace(_FwdIt_First,_FwdIt_Last,
const_Ty&_Oldval,const_Ty&_Newval)
{
//replaceeachmatching_Oldvalwith_Newval
_Replace(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Oldval,_Newval);
}


//TEMPLATEFUNCTIONreplace_copy
template<class_InIt,class_OutIt,class_Ty,class_InOutItCat>
inline
_OutIt_Replace_copy(_InIt_First,_InIt_Last,_OutIt_Dest,
const_Ty&_Oldval,const_Ty&_Newval,
_InOutItCat,_Range_checked_iterator_tag)
{
//copyreplacingeachmatching_Oldvalwith_Newval
_DEBUG_RANGE(_First,_Last);
_DEBUG_POINTER(_Dest);
for(;_First!=_Last;++_First,++_Dest)
*_Dest=*_First==_Oldval?_Newval:*_First;
return(_Dest);
}

template<class_InIt,
class_OutIt,
class_Ty>inline
_IF_CHK(_OutIt)replace_copy(_InIt_First,_InIt_Last,_OutIt_Dest,
const_Ty&_Oldval,const_Ty&_Newval)
{
//copyreplacingeachmatching_Oldvalwith_Newval
return_Replace_copy(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,_Oldval,_Newval,
_Iter_random(_First,_Dest),_STD_Range_checked_iterator_tag());
}



//TEMPLATEFUNCTIONreplace_copy_if
template<class_InIt,class_OutIt,class_Pr,class_Ty,class_InOutItCat>
inline
_OutIt_Replace_copy_if(_InIt_First,_InIt_Last,_OutIt_Dest,
_Pr_Pred,const_Ty&_Val,_InOutItCat,_Range_checked_iterator_tag)
{
//copyreplacingeachsatisfying_Predwith_Val
_DEBUG_RANGE(_First,_Last);
_DEBUG_POINTER(_Dest);
_DEBUG_POINTER(_Pred);
for(;_First!=_Last;++_First,++_Dest)
*_Dest=_Pred(*_First)?_Val:*_First;
return(_Dest);
}


template<class_InIt,
class_OutIt,
class_Pr,
class_Ty>inline
_IF_CHK(_OutIt)replace_copy_if(_InIt_First,_InIt_Last,_OutIt_Dest,
_Pr_Pred,const_Ty&_Val)
{
//copyreplacingeachsatisfying_Predwith_Val
return_Replace_copy_if(_CHECKED_BASE(_First),_CHECKED_BASE(_Last),_Dest,_Pred,_Val,
_Iter_random(_First,_Dest),_STD_Range_checked_iterator_tag());
}

replace 带4个参数,将前两个参数指示的区间元素值为_Oldval 的替换成_Newval。


if(*_First==_Oldval)


*_First=_Newval;


replace_copy 带5个参数,先将前两个参数指示区间的元素都拷贝到第三个参数指示的区间上,再判断是否执行replace。


*_Dest=*_First==_Oldval?_Newval:*_First; 每个元素拷贝后,判断是_Oldval 则替换,否则还是原值。


replace_copy_if 带5个参数,在每个元素拷贝时先判断是否满足条件(函数返回为真),满足则替换成_Val,否则保持不变。


*_Dest=_Pred(*_First)?_Val:*_First;



示例代码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> 36<br> 37<br> 38<br> 39<br> 40<br></nobr>
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
usingnamespacestd;

voidprint_element(intn)
{
cout<<n<<'';
}

boolfun(inta)
{
returna<10;
}

intmain(void)
{
inta[]={1,2,3,4,3};
vector<int>v(a,a+5);
list<int>l(5);

replace(v.begin(),v.end(),3,13);
for_each(v.begin(),v.end(),print_element);
cout<<endl;

replace_copy(v.begin(),v.end(),l.begin(),13,3);
for_each(v.begin(),v.end(),print_element);
cout<<endl;

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

replace_copy_if(v.begin(),v.end(),l.begin(),fun,0);
for_each(l.begin(),l.end(),print_element);
cout<<endl;


return0;
}

输出为:

1 2 13 4 13

1 2 13 4 13

1 2 3 4 3

0 0 13 0 13


参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范


分享到:
评论

相关推荐

    微软c++ STL源代码

    微软c++ STL源代码微软c++ STL源代码微软c++ STL源代码微软c++ STL源代码微软c++ STL源代码微软c++ STL源代码微软c++ STL源代码微软c++ STL源代码微软c++ STL源代码微软c++ STL源代码微软c++ STL源代码微软c++ STL源...

    C++ STL--数据结构与算法实现(余文溪)示例程序代码.rar

    余文溪的《C++ STL--数据结构与算法实现》这本书很可能详细介绍了如何利用STL来解决实际问题,并通过示例程序代码来加深理解。 STL中的核心概念有以下几个: 1. 容器(Containers):这是STL的基础,它们是存储...

    C++ STL库源代码(SGI版本)

    在这个“C++ STL库源代码(SGI版本)”中,我们主要关注的是SGI(Stanford Graphics Interface)实现的版本,这是一个广泛使用的开源实现,对STL进行了优化和扩展。 1. **algorithm**: 这个目录包含了许多通用的算法...

    C++库函数及STL算法

    此外,STL的算法如`std::transform`和`std::accumulate`可以简化复杂的计算过程,提高代码的可读性和可维护性。 总的来说,理解和熟练运用C++库函数与STL是成为专业C++程序员的关键步骤。它们是C++语言的精华,也是...

    STL算法备忘单+来自STL算法视频系列的示例代码_C++_下载.zip

    这份“STL算法备忘单+来自STL算法视频系列的示例代码”资源,显然是为了帮助开发者更好地理解和运用STL中的算法。下面我们将深入探讨STL算法的主要部分及其在实际编程中的应用。 1. **容器**:STL的核心之一是容器...

    c++ SGI STL源代码学习

    它为C++程序员提供了丰富的容器、迭代器、算法和函数对象,极大地提高了代码的可重用性和效率。侯捷老师推荐的这份SGI STL源代码,是深入理解C++ STL内部实现机制的重要资料,对于提升C++编程技能和优化代码性能有着...

    【STL源代码】C++标准库STL源代码下载

    阅读STL源代码可以帮助我们理解C++容器和算法的底层实现,从而优化自己的代码,提高程序性能。同时,也能让我们更好地掌握C++模板机制,以及如何利用泛型编程来编写高效且可复用的代码。通过分析源码,我们可以学习...

    c++ STL源代码

    3. 算法:STL提供了大量预定义的算法,如排序(sort)、查找(find)、复制(copy)等,这些算法通常与迭代器一起使用,可以应用于任何容器。例如,`std::sort`可以对容器内的元素进行排序,`std::find`则用于在容器...

    C++ STL标准程序库开发指南 源代码.rar

    这个压缩包“C++ STL标准程序库开发指南 源代码.rar”包含了C++ STL的源代码,对于学习和理解STL的内部实现机制非常有帮助。下面我们将深入探讨STL的关键组件、它们的工作原理以及如何通过源代码进行学习。 1. **...

    c++STL学习——各种变异算法技术总结和用法代码实例(1)

    在这个“C++ STL学习——各种变异算法技术总结和用法代码实例(1)”的主题中,我们将深入探讨STL中的变异算法,这些算法用于改变容器中元素的排列或状态。以下是一些主要的变异算法及其详细解释: 1. **交换算法(`...

    stl的学习:c++ STL

    STL,全称为Standard Template Library(标准模板库),是C++编程语言中不可或缺的一部分,它为程序员提供了高效且可重用的数据结构和算法。STL的主要组成部分包括容器、迭代器、算法和函数对象,这些组件共同构成了...

    C++_STL库_源代码

    它是C++标准库的一部分,提供了丰富的数据结构和算法,极大地提升了开发效率和代码复用性。STL的核心概念包括容器、迭代器、算法和函数对象。 1. 容器: STL容器是一组对象的集合,它们可以存储、组织和管理其他...

    c++STL学习——各种变异算法技术总结和用法代码实例(2)

    - `std::copy_backward` 与`std::copy`类似,但它是从后向前复制,通常用于避免在目标范围内可能出现的元素覆盖问题。 5. **删除算法(remove、erase)**: - `std::remove` 不会真的删除元素,而是将所有待删除...

    c++ STL 库使用示例

    - **复制算法**:`copy()`、`copy_backward()`用于元素的复制。 - **其他**:还包括`generate()`、`transform()`、`unique()`、`reverse()`等。 4. 仿函数(函数对象): - 例如`std::less`、`std::greater`用于...

    C++类库与算法 STL 算法与分析 皇后问题回溯法实现程序源代码 回溯法示例代码

    本主题聚焦于C++类库与算法的应用,特别是标准模板库(STL)中的算法,并通过一个具体的实例——皇后问题的回溯法实现来深入探讨。 皇后问题是一个经典的计算机科学问题,它要求在棋盘上放置N个皇后,使得任意两个...

    从零开始学c++(ppt)

    《从零开始学C++》是一份专为初学者设计的教学资料,旨在引导学习者逐步掌握C++编程语言。这份教程包含丰富的基础知识讲解,搭配教案和源代码,使得学习过程更具实践性和互动性。 首先,从C++的基础部分开始,学习...

    C++ STL标准程序库实例源代码

    C++ STL(Standard Template Library,标准模板库)是C++编程...通过学习和实践这些C++ STL标准程序库实例源代码,开发者可以深入理解STL的工作原理,掌握如何有效地利用其功能来编写高效、简洁和易于维护的C++代码。

    C++ stl算法汇总(C++程序员必备)

    C++ STL(Standard Template Library,标准模板库)是C++编程中极其重要的组成部分,它提供了一组高效且灵活的算法,用于处理各种数据结构,如向量、列表、集合等。这些算法通常与容器(如vector、list)配合使用,...

    C++STL源码分析 SGI版

    对于初学者,建议先从简单的容器和算法开始,逐步熟悉STL的基本用法。然后,通过阅读源码理解容器和迭代器的内部结构,再深入研究复杂的算法和函数对象。最后,可以尝试自己实现一些STL组件,以加深理解。 5. **...

Global site tag (gtag.js) - Google Analytics