STL源代码分析——STL算法remove删除算法

STL源代码分析——STL算法remove删除算法

前言

    因为在前文的《STL算法剖析》中,源代码剖析许多。不方便学习,也不方便以后复习,这里把这些算法进行归类。对他们单独的源代码剖析进行解说。本文介绍的STL算法中的remove删除算法。源代码中介绍了函数removeremove_copyremove_ifremove_copy_ifuniqueunique_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源代码分析》侯杰

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109213.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 怎么保证RabbitMQ和kafuka集群的高可用性?

    怎么保证RabbitMQ和kafuka集群的高可用性?rabbitMQ有三种模式:单机模式,普通集群模式,镜像集群模式 RabbitMQ的高可用性 RabbitMQ是比较有代表性的,因为是基于主从做高可用性的,我们就以他为例子讲解第一种MQ的高可用性怎么实现。 rabbitmq有三种模式:单机模式,普通集群模式,镜像集群模式 1)单机模式 就是demo级别的,一般就…

    2022年6月1日
    40
  • Web Service进阶(一)运行原理[通俗易懂]

    Web Service进阶(一)运行原理[通俗易懂]利用清明小假期,温习了一遍WebService的相关内容,对其工作原理进行了简要总结。以供有需求的朋友和自己日后参考。文章若有不当之处,敬请朋友们提出宝贵建议,以求共勉。Web服务中,我们应该首先了解相关的术语含义:WSDL、UDDI….相关术语方面的介绍在此不再赘述,重点放在原理上。在Web服务中,存在三个角色:服务提供者、服务请求者和服务中介,三者之间的关系如图1…

    2022年7月24日
    13
  • oracle创建索引的sql语句_mysql创建组合索引

    oracle创建索引的sql语句_mysql创建组合索引Oracle创建索引

    2025年9月13日
    5
  • 孙鑫老师 java从入门到精通 视频教程 批量下载

    孙鑫老师 java从入门到精通 视频教程 批量下载本视频教程是孙鑫老师亲自开发录制的,内容涵盖了java技术从入门到精通整个过程。对于java爱好者是一套不可多得的教材!相信下载此教程的同志都是未来的电脑高手,对于批量下载的方法我在这时就不一一说了,相信兄弟们都能找到这种简单规律。这里以第三课批量下载为例简单说一下:(记得将通配符长度设为1哦)第一课Java的一些基本概念http://www.ibook8.com/te

    2022年5月17日
    39
  • 填充墙一般用什么材料_opencv填充封闭区域

    填充墙一般用什么材料_opencv填充封闭区域目录一、须知二、演示过程代码展示主函数展示原图运行结果三、总结一、须知本文章所提供代码不是自创,由于时间太久实在找不到来源,发布出来只为给大家提供便利,完全免费。话不多说,不想看文章的直接点击下载链接即可:点我.二、演示过程代码展示Matcop二值图intn填充比n小的孔洞函数默认为4连通如想改为8连通自行修改代码即可。#include”imfill.h”Matimfill(Matcop,intn){ Matdata=~cop; Matlabels,

    2025年11月3日
    3
  • 新手小白学JAVA 面向对象之多态

    新手小白学JAVA 面向对象之多态4多态4.1概念多态指同一个实体同时具有多种形式它是面向对象程序设计(OOP)的一个重要特征。主要是指同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。好处是:可以把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。水果有两种形态:水果和苹果,不关心买回来的是苹果还是西瓜,只要是水果就行classAnimal{//1.定义父类Animal…eat(){syso(“吃啥都行”)}}classCatexte

    2022年7月19日
    14

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号