STL源码剖析学习十五:算法之其他算法
寻找相等的相邻元素
adjacent_find(first, last) { if(first == last) return last; ForwardIterator next = first; while(++next != last) { if(*next == *first) return first; first = next; } return last; }
统计与value元素相等的元素的个数
template <class InputIterator, class T> typename iterator_traits<InputIterator>::difference_type count(first, last, value) { //关键在于计数器的声明 typename iterator_traits<InputIterator>::difference_type n = 0; for(; first!=last; ++first) { if(*first == value) ++n; } return n; }
count_if提供一个仿函数用来判断两个元素相等的条件
查找元素
find(first, last, value) { while(first!=last && *first!=value) ++first; return first; }
find_if提供一个仿函数用来判断两个元素相等的条件
在序列一中查找序列2的最后一次的出现点
又用到了双层迭代器的架构,令函数调用过程中产生迭代器类型的临时对象,再利用编译器的参数推导机制自动调用某个对应函数
上层函数一般称为分派函数
find_end(first1, last1, first2, last2) { typedef typename iterator_traits<ForwardIterator1>::iterator_category category1; typedef typename iterator_traits<ForwardIterator1>::iterator_category category1; return __find_end(first1, last1, first2, last2, categroy1(), category2()); } __find_end(first1, last1, first2, last2, forward_iterator_tag, forward_iterator_tag) { if(first2 == last2) return last1; else { ForwardIterator1 result = last1; while(1) { //用search来查找符合条件的区间 ForwardIterator1 new_result = search(first1, last1, first2, last2); if(new_result == last1) return result;//没有找到就返回 else//如果找到就记录下本次查找的结果,并且调整迭代器准备下一次查找 { result = new_result; first = new_result; ++first; } } } }
查找序列2内任意一个元素在序列1内第一次出现的位置
find_first_of(first1, last1, first2, last2) { for(; first!=last1; ++first1) { for(ForwardIterator ite=first2; ite!=last2; ++ite) { if(*ite == *first) return first; } } return last1; }
将仿函数f实行于区间内的每一个元素上,f不可以改变元素的内容,要修改元素内容用transform
//其实f是可以修改元素内容的,只要在定义仿函数时将传入元素的引用就可以了
for_each(first, last, f) { for(; first!=last; ++first) f(*first); return f //返回的是仿函数 }
将仿函数f作用于每一个元素并且将结果输出到另一个序列
如果目的迭代器指向源序列的起点,那么他就会替代原来的元素
transform(first, last, result, op) { for(; first!=last; ++first, ++result) *result = op(*first); return result //返回的是结果序列的最后一个元素的下一位置 }
将仿函数gen的运算结果写在区间内
generate(first, last, gen) { for(; first!=last; ++first) *first = gen(); }
给个仿函数写法的例子
class even_by_two { public: int operator()()const { return _x += 2; } private: static _x; } int even_by_two::_x = 0;
generate_n将结果填写到前n个位置中
判断序列1是否包含序列2,必须用于有序区间
includes(first1, last1, first2, last2) { while(first1!=last1 && first2!=last2) { if(*first1<*first2) { ++first1; } else if(*first2<*first1) { return false; } else { ++first1; ++first2; } } return first2 == last2 //保证序列2中的元素都被遍历到 }
如果要提供comp比较函数来判断两个元素是否相等
则必须符合
if(comp(*first1, *first2))
.......
else if(comp(*first2, *first1))
......
else
....
用这种方式可以判断两个元素的大于小于等于,否则就会出错
合并两个区间,并且写到新的区间中,作用于有序区间(类似于求交集)
merge(first1, last1, first2, last2, result) { while(first1!=last1 && first2!=last2) { if(*first1 < *first2) { *result = *first1; ++first1; } else if(*first2 < *first1) { *result = *first2; ++first2; } else { *result = *first1; ++first1; ++first2; } ++result; } return copy(first1, last1, copy(first2, last2)); }
将区间内的元素重新排列,用仿函数pred判定为为true的元素都放在前段,false的元素都放在后段
不保证元素之间的相对位置,如果需要,就用stable_partition
partition(first, last, pred) { while(1) { while(1) { if(first == last) return first; else if( pred(*first) ) ++first; else break; } --last; while(1) { if(first == last) return first; else if( !pred(*last) ) --last; else break; } iter_swap(first, last); ++first; } }
移除(但不是删除)
把每一个与value不相等的元素轮番复制给first之后的空间,
返回值指向重新整理后的最后元素的下一个位置。
如果要从实际上删除则调用erase
array不适用remove,因为其尺寸无法缩小,最好使用remove_copy和remove_copy_if
remove(first, last, value) { first = find(first, last, value); //找到第一个相等的元素的位置,从该位置之后的一个位置开始拷贝 //利用remove_copy允许新旧容器重叠的特性进行移除操作 ForwardIterator next = first; return first == last? first: remove_copy(++next, last, first, value); }
remove_if提供一个仿函数可以判断元素值是否跟value相等
移除区间中和value相等的元素,并把结果拷贝到新的容器中,新旧容器可以重叠
remove_copy(first, last, result, value) { for(; first!=last; ++first) { if(*first != value) *result = *first; ++result; } return first; }
remove_copy_if提供一个仿函数可以判断元素值是否跟value相等
待续~~~~~~~~
浙公网安备 33010602011771号