前言

因为在前文的《STL算法剖析》中,源代码剖析许多。不方便学习,也不方便以后复习,这里把这些算法进行归类。对他们单独的源代码剖析进行解说。本文介绍的STL算法中的remove删除算法。源代码中介绍了函数remove、remove_copy、remove_if、remove_copy_if、unique、unique_copy。

并对这些函数的源代码进行具体的剖析。并适当给出使用样例,具体详见以下源代码剖析。

remove移除算法源代码剖析

// remove, remove_if, remove_copy, remove_copy_if

//移除[first,last)区间内全部与value值相等的元素,并非真正的从容器中删除这些元素(原容器的内容不会改变)
//而是将结果拷贝到一个以result为起始位置的容器中。新容器能够与原容器重叠
template <class _InputIter, class _OutputIter, class _Tp>
_OutputIter remove_copy(_InputIter __first, _InputIter __last,
_OutputIter __result, const _Tp& __value) {
__STL_REQUIRES(_InputIter, _InputIterator);
__STL_REQUIRES(_OutputIter, _OutputIterator);
__STL_REQUIRES_BINARY_OP(_OP_EQUAL, bool,
typename iterator_traits<_InputIter>::value_type, _Tp);
for ( ; __first != __last; ++__first)//遍历容器
if (!(*__first == __value)) {//假设不相等
*__result = *__first;//赋值给新容器
++__result;//新容器前进一个位置
}
return __result;
}
//移除[first,last)区间内被仿函数pred推断为true的元素,并非真正的从容器中删除这些元素(原容器的内容不会改变)
//而是将结果拷贝到一个以result为起始位置的容器中。新容器能够与原容器重叠
template <class _InputIter, class _OutputIter, class _Predicate>
_OutputIter remove_copy_if(_InputIter __first, _InputIter __last,
_OutputIter __result, _Predicate __pred) {
__STL_REQUIRES(_InputIter, _InputIterator);
__STL_REQUIRES(_OutputIter, _OutputIterator);
__STL_UNARY_FUNCTION_CHECK(_Predicate, bool,
typename iterator_traits<_InputIter>::value_type);
for ( ; __first != __last; ++__first)//遍历容器
if (!__pred(*__first)) {//若pred推断为false
*__result = *__first;//赋值给新容器
++__result;//新容器前进一个位置
}
return __result;
}
//移除[first,last)区间内全部与value值相等的元素,该操作不会改变容器大小。仅仅是容器中元素值改变
//即移除之后,又一次整理容器的内容
template <class _ForwardIter, class _Tp>
_ForwardIter remove(_ForwardIter __first, _ForwardIter __last,
const _Tp& __value) {
__STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
__STL_REQUIRES_BINARY_OP(_OP_EQUAL, bool,
typename iterator_traits<_ForwardIter>::value_type, _Tp);
__STL_CONVERTIBLE(_Tp, typename iterator_traits<_ForwardIter>::value_type);
__first = find(__first, __last, __value);//利用顺序查找找出第一个与value相等的元素
_ForwardIter __i = __first;
//以下调用remove_copy
return __first == __last ? __first
: remove_copy(++__i, __last, __first, __value);
}
//移除[first,last)区间内全部被pred推断为true的元素,该操作不会改变容器大小,仅仅是容器中元素值改变
//即移除之后,又一次整理容器的内容
template <class _ForwardIter, class _Predicate>
_ForwardIter remove_if(_ForwardIter __first, _ForwardIter __last,
_Predicate __pred) {
__STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
__STL_UNARY_FUNCTION_CHECK(_Predicate, bool,
typename iterator_traits<_ForwardIter>::value_type);
__first = find_if(__first, __last, __pred);//利用顺序查找找出第一个与value相等的元素
_ForwardIter __i = __first;
//以下调用remove_copy_if
return __first == __last ? __first
: remove_copy_if(++__i, __last, __first, __pred);
}
//上面四个移除函数举例:
/*
#include <iostream> // std::cout
#include <algorithm> // std::remove bool IsOdd (int i) { return ((i%2)==1); } int main () {
int myints[] = {10,20,31,30,20,11,10,20}; // 10 20 31 30 20 11 10 20 std::vector<int> myvector (8);
std::remove_copy (myints,myints+8,myvector.begin(),20); // 10 31 30 11 10 0 0 0
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n'; // bounds of range:
int* pbegin = myints; // ^
int* pend = myints+sizeof(myints)/sizeof(int); // ^ ^
pend = std::remove (pbegin, pend, 20); // 10 31 30 11 10 ? ? ?
// ^ ^
std::cout << "range contains:";
for (int* p=pbegin; p!=pend; ++p)
std::cout << ' ' << *p;
std::cout << '\n'; std::vector<int> myvector2 (7);
std::remove_copy_if (myints,myints+7,myvector2.begin(),IsOdd);
std::cout << "myvector2 contains:";
for (std::vector<int>::iterator it=myvector2.begin(); it!=myvector2.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n'; pend = std::remove_if (pbegin, pend, IsOdd); // 10 30 10 ? ? ? ? ? // ^ ^
std::cout << "the range contains:";
for (int* p=pbegin; p!=pend; ++p)
std::cout << ' ' << *p;
std::cout << '\n'; return 0;
}
Output:
myvector contains: 10 31 30 11 10 0 0 0
range contains: 10 31 30 11 10
myvector2 contains: 10 30 10 10 0 0 0
the range contains: 10 30 10
*/ // unique and unique_copy template <class _InputIter, class _OutputIter, class _Tp>
_OutputIter __unique_copy(_InputIter __first, _InputIter __last,
_OutputIter __result, _Tp*) {
_Tp __value = *__first;
*__result = __value;
while (++__first != __last)
if (!(__value == *__first)) {
__value = *__first;
*++__result = __value;
}
return ++__result;
}
//若result类型为output_iterator_tag,则调用该函数
template <class _InputIter, class _OutputIter>
inline _OutputIter __unique_copy(_InputIter __first, _InputIter __last,
_OutputIter __result,
output_iterator_tag) {
//推断first的value_type类型,依据不同类型调用不同函数
return __unique_copy(__first, __last, __result, __VALUE_TYPE(__first));
}
//若result类型为forward_iterator_tag,则调用该函数
template <class _InputIter, class _ForwardIter>
_ForwardIter __unique_copy(_InputIter __first, _InputIter __last,
_ForwardIter __result, forward_iterator_tag) {
*__result = *__first;//记录第一个元素
while (++__first != __last)//遍历区间
//若不存在相邻反复元素,则继续记录到目标区result
if (!(*__result == *__first))
*++__result = *__first;//记录元素到目标区
return ++__result;
}
////unique_copy将区间[first,last)内元素拷贝到以result开头的区间上,可是假设存在相邻反复元素时,仅仅复制当中第一个元素
//和unique一样。这里也有两个版本号
/*
函数原型:
equality (1)
template <class InputIterator, class OutputIterator>
OutputIterator unique_copy (InputIterator first, InputIterator last,
OutputIterator result);
predicate (2)
template <class InputIterator, class OutputIterator, class BinaryPredicate>
OutputIterator unique_copy (InputIterator first, InputIterator last,
OutputIterator result, BinaryPredicate pred);
*/
//版本号一
template <class _InputIter, class _OutputIter>
inline _OutputIter unique_copy(_InputIter __first, _InputIter __last,
_OutputIter __result) {
__STL_REQUIRES(_InputIter, _InputIterator);
__STL_REQUIRES(_OutputIter, _OutputIterator);
__STL_REQUIRES(typename iterator_traits<_InputIter>::value_type,
_EqualityComparable);
if (__first == __last) return __result;
//依据result迭代器的类型,调用不同的函数
return __unique_copy(__first, __last, __result,
__ITERATOR_CATEGORY(__result));
} template <class _InputIter, class _OutputIter, class _BinaryPredicate,
class _Tp>
_OutputIter __unique_copy(_InputIter __first, _InputIter __last,
_OutputIter __result,
_BinaryPredicate __binary_pred, _Tp*) {
__STL_BINARY_FUNCTION_CHECK(_BinaryPredicate, bool, _Tp, _Tp);
_Tp __value = *__first;
*__result = __value;
while (++__first != __last)
if (!__binary_pred(__value, *__first)) {
__value = *__first;
*++__result = __value;
}
return ++__result;
} template <class _InputIter, class _OutputIter, class _BinaryPredicate>
inline _OutputIter __unique_copy(_InputIter __first, _InputIter __last,
_OutputIter __result,
_BinaryPredicate __binary_pred,
output_iterator_tag) {
return __unique_copy(__first, __last, __result, __binary_pred,
__VALUE_TYPE(__first));
} template <class _InputIter, class _ForwardIter, class _BinaryPredicate>
_ForwardIter __unique_copy(_InputIter __first, _InputIter __last,
_ForwardIter __result,
_BinaryPredicate __binary_pred,
forward_iterator_tag) {
__STL_BINARY_FUNCTION_CHECK(_BinaryPredicate, bool,
typename iterator_traits<_ForwardIter>::value_type,
typename iterator_traits<_InputIter>::value_type);
*__result = *__first;
while (++__first != __last)
if (!__binary_pred(*__result, *__first)) *++__result = *__first;
return ++__result;
}
//版本号二
template <class _InputIter, class _OutputIter, class _BinaryPredicate>
inline _OutputIter unique_copy(_InputIter __first, _InputIter __last,
_OutputIter __result,
_BinaryPredicate __binary_pred) {
__STL_REQUIRES(_InputIter, _InputIterator);
__STL_REQUIRES(_OutputIter, _OutputIterator);
if (__first == __last) return __result;
//依据result迭代器的类型,调用不同的函数
return __unique_copy(__first, __last, __result, __binary_pred,
__ITERATOR_CATEGORY(__result));
}
//移除区间[first,last)相邻连续反复的元素
//unique有两个版本号
//功能:Removes all but the first element from every consecutive group of equivalent elements in the range [first,last).
/*
函数原型:
equality (1):版本号一採用operator==
template <class ForwardIterator>
ForwardIterator unique (ForwardIterator first, ForwardIterator last);
predicate (2):版本号二採用pred操作
template <class ForwardIterator, class BinaryPredicate>
ForwardIterator unique (ForwardIterator first, ForwardIterator last,
BinaryPredicate pred);
*/
//版本号一
template <class _ForwardIter>
_ForwardIter unique(_ForwardIter __first, _ForwardIter __last) {
__STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
__STL_REQUIRES(typename iterator_traits<_ForwardIter>::value_type,
_EqualityComparable);
__first = adjacent_find(__first, __last);//找出第一个相邻元素的起始位置
return unique_copy(__first, __last, __first);//调用unique_copy完毕操作
}
//版本号二
template <class _ForwardIter, class _BinaryPredicate>
_ForwardIter unique(_ForwardIter __first, _ForwardIter __last,
_BinaryPredicate __binary_pred) {
__STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
__STL_BINARY_FUNCTION_CHECK(_BinaryPredicate, bool,
typename iterator_traits<_ForwardIter>::value_type,
typename iterator_traits<_ForwardIter>::value_type);
__first = adjacent_find(__first, __last, __binary_pred);//找出第一个相邻元素的起始位置
return unique_copy(__first, __last, __first, __binary_pred);//调用unique_copy完成操作
}

参考资料:

《STL源代码分析》侯杰

STL源代码分析——STL算法remove删除算法的更多相关文章

  1. STL源代码分析——STL算法merge合并算法

    前言 因为在前文的<STL算法剖析>中.源代码剖析许多.不方便学习.也不方便以后复习,这里把这些算法进行归类.对他们单独的源代码剖析进行解说.本文介绍的STL算法中的merge合并算法. ...

  2. STL源代码分析——STL算法sort排序算法

    前言 因为在前文的<STL算法剖析>中,源代码剖析许多,不方便学习,也不方便以后复习.这里把这些算法进行归类,对他们单独的源代码剖析进行解说.本文介绍的STL算法中的sort排序算法,SG ...

  3. Java中数组的几个常用算法:插入算法,删除算法,冒泡排序算法

    前言: 在Java中我们常常会用数组,提到数组就不得不介绍数组中常用到的几个算法. 有插入算法,删除算法,冒泡排序算法等. 在学习这几个数组的算法前,我们先来了解一下关于数组一些基本知识. 数组的基本 ...

  4. STL源代码剖析——STL算法stl_algo.h

    前言 在前面的博文中剖析了STL的数值算法.基本算法和set集合算法.本文剖析STL其它的算法,比如排序算法.合并算法.查找算法等等.在剖析的时候.会针对函数给出一些样例说明函数的使用.源代码出自SG ...

  5. STL源代码剖析——STL算法之set集合算法

    前言 本节介绍set集合的相关算法,各自是并集set_union,差集set_difference,交集set_intersection 和对称差集set_symmetric_difference.这 ...

  6. STL源代码分析--萃取编程(traits)技术的实现

    1.为什么要出现? 依照默认认定.一个模板给出了一个单一的定义,能够用于用户能够想到的不论什么模板參数!可是对于写模板的人而言,这样的方式并不灵活.特别是遇到模板參数为指针时,若想实现与类型的參量不一 ...

  7. STL 源代码分析 算法 stl_heap.h

    本文senlie原版的.转载请保留此地址:http://blog.csdn.net/zhengsenlie heap ----------------------------------------- ...

  8. STL 源代码分析 算法 stl_algo.h -- includes

    本文senlie原,转载请保留此地址:http://blog.csdn.net/zhengsenlie includes(应用于有序区间) ------------------------------ ...

  9. STL 源代码分析 算法 stl_algo.h -- merge

    本文senlie原版的,转载请保留此地址:http://blog.csdn.net/zhengsenlie merge (应用于有序区间) ------------------------------ ...

随机推荐

  1. Processing_百度百科

    Processing_百度百科 Processing

  2. hibernate.cfg.xml文件的配置模板和不同数据库的配置參数

    (1)hibernate.cfg.xml文件的配置模板 <?xml version="1.0" encoding="UTF-8"?> <!DO ...

  3. cocos2d/-x 用CCRenderTexture为一个CCLabelTTF创建阴影。

    游戏UI中为了使字体更加漂亮,通常需要为字体添加一个阴影.其实不用美工,程序就可以添加.先为CCLabelTTF创建一个CCRenderTexture: CCRenderTexture* CCLabe ...

  4. 模拟new实例化对象。

    使用new和字面量的的方法是两种主流创建对象的方法,两种最终都能达到同样的实例化的对象,本章主要围绕new关键字来实例化一个对象并且讲一个不使用new但是完全与new实例化对象相同的例子. 在使用ne ...

  5. 与众不同 windows phone (32) - Communication(通信)之任意源组播 ASM(Any Source Multicast)

    原文:与众不同 windows phone (32) - Communication(通信)之任意源组播 ASM(Any Source Multicast) [索引页][源码下载] 与众不同 wind ...

  6. objective-c 中数据类型之六 数值类(NSValue)

    // NSValue能够将c类型转换为Objective-C对象,如NSRange,CGPoint.CGSize,CGRect,CGVector,UIEdgeInsets,UIOffset NSRan ...

  7. Linux Socket编程注意事项

    Socket API 是网络应用程序开发中实际应用的标准 API.虽然该 API 简单.可是开发新手可能会经历一些常见的问题.本文识别一些最常见的隐患并向您显示怎样避免它们. 隐患 1.忽略返回状态 ...

  8. Android实现位图剪切

    我们不能总是依赖于BitmapFactory 以下告诉大家怎么从Bitmaqp中截取某一部分创建新的Bitmap  系统会有一个默认png图片:icon.png 可是这个图片中最外层会有白色的 比較讨 ...

  9. Android常用开源项目

    Android开源项目第一篇——个性化控件(View)篇   包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.Progre ...

  10. TestApe - Unit testing for embedded software

    TestApe - Unit testing for embedded software About this site Welcome - This site is TestApe.com. Mos ...