STL函数详解:
- 查找函数:find()、find_if()、adjacent_find()、find_first_of()、find_end();
- 计数函数:count()、count_if();
- 匹配函数:mismatch()、equal();
- 查找函数:search()、search_n();
- 复制函数:copy()、copy_backward();
- 交换函数:swap()、iter_swap()、swap_ranges();
- 转换函数:transform();
- 替换函数:replace()。
1. for_each()
for_each 算法将范围 [begin, end) 中的每个元素调用函数 F,并返回输入的参数 f。此函数不会修改序列中的任何元素。
template<class InputIterator, class Function>
Function for_each(
InputIterator _First,
InputIterator _Last,
Function _Func
);
//print为仿函数
struct print{
int count;
print(){count = 0;}
void operator()(int x)
{
cout << x << endl;
++count;
}
};
list<int> ilist;
//遍历ilist元素并打印
print p = for_each(ilist.begin(), ilist.end(), print());
仿函数,又或叫做函数对象,是STL(标准模板库)六大组件(容器、配置器、迭代器、算法、配接器、仿函数)之一;仿函数虽然小,但却极大的拓展了算法的功能,几乎所有的算法都有仿函数版本。例如,查找算法find_if就是对find算法的扩展,标准的查找是两个元素向等就找到了,但是什么是相等在不同情况下却需要不同的定义,如地址相等,地址和邮编都相等,虽然这些相等的定义在变,但算法本身却不需要改变,这都多亏了仿函数。 仿函数之所以叫做函数对象,是因为仿函数都是定义了()函数运算操作符的类。
class ObjectFunction2
{
public:
bool operator() (int x)
{
count << "Have Param ObjectFuntion" << endl;
count << "This is ObjectFuntion's Param" << x << endl;
return true;
}
}
2.find()
find算法用于查找等于某值的元素。它在迭代器区间[begin, end)上查找等于value值的元素,如果迭代器iter所指的元素满足 *iter == value ,则返回迭代器iter,未找则返回end。
template<class InputIterator, class Type>
InputIterator find(
InputIterator _First,
InputIterator _Last,
const Type& _Val
);
list<int>::iterator iLocation = find(ilist.begin(), ilist.end(), 10);
if (iLocation != ilist.end())
{
cout << "找到元素 10" << endl;
}
3.find_if()
find_if算法 是find的一个谓词判断版本,它利用返回布尔值的谓词判断pred,检查迭代器区间[begin, end)上的每一个元素,如果迭代器iter满足pred(*iter) == true,表示找到元素并返回迭代器值iter;未找到元素,则返回end。
template<class InputIterator, class Predicate>
InputIterator find_if(
InputIterator _First,
InputIterator _Last,
Predicate _Pred
);
//谓词判断函数 divbyfive : 判断x是否能5整除
bool divbyfive(int x)
{
return x % 5 ? 0 : 1;
}
vector<int> iVect(20);
vector<int>::iterator iLocation;
iLocation = find_if(iVect.begin(), iVect.end(), divbyfive);
if (iLocation != iVect.end())
{
cout << "第一个能被5整除的元素为:"<< *iLocation << endl //打印元素:15
<< "元素的索引位置为:"<< iLocation - iVect.begin() << endl; //打印索引位置:2
}
4.adjacent_find()
adjacent_find算法用于查找相等或满足条件的邻近元素对。其有两种函数原型:一种在迭代器区间[begin, end)上查找两个连续的元素相等时,返回元素对中第一个元素的迭代器位置。另一种是使用二元谓词判断binary_pred,查找迭代器区间[begin, end)上满足binary_pred条件的邻近元素对,未找到则返回end。
<strong>template<class ForwardIterator>
ForwardIterator adjacent_find(
ForwardIterator _First,
ForwardIterator _Last
);
template<class ForwardIterator , class BinaryPredicate>
ForwardIterator adjacent_find(
ForwardIterator _First,
ForwardIterator _Last,
BinaryPredicate _Comp
);
</strong>
//判断X和y是否奇偶同性
bool parity_equal(int x, int y)
{
return (x - y) % 2 == 0 ? 1 : 0;
}
list<int> iList;
list<int>::iterator iter;
//查找邻接相等的元素
list<int>::iterator iResult = adjacent_find(iList.begin(), iList.end());
if (iResult != iList.end())
{
cout << "链表中第一对相等的邻近元素为:" << endl;
cout << *iResult++ << endl;
cout << *iResult << endl;
}
//查找奇偶性相同的邻近元素
iResult = adjacent_find(iList.begin(), iList.end(), parity_equal);
if (iResult != iList.end())
{
cout << "链表中第一对奇偶相同的元素为:" << endl;
cout << *iResult++ << endl;
cout << *iResult << endl;
}
return 0;
5.find_first_of()
find_first_of算法用于查找位于某个范围之内的元素。它有两个使用原型,均在迭代器区间[begin1, end1)上查找元素*i,使得迭代器区间[begin2, end2)某个元素*j,满足*i ==*j或满足二元谓词函数comp(*i, *j)==true的条件。元素找到则返回迭代器i,否则返回end1。
template<class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 find_first_of(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2
);
template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
ForwardIterator1 find_first_of(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2,
BinaryPredicate _Comp
);
const char* strOne = "abcdef1212daxs";
const char* strTwo = "2ef";
const char* result = find_first_of(strOne, strOne + strlen(strOne),strTwo, strTwo + strlen(strTwo));
cout << "字符串strOne中第一个出现在strTwo的字符为:"<< *result << endl;
6.find_end()
find_end算法在一个序列中搜索出最后一个与另一序列匹配的子序列。有如下两个函数原型,在迭代器区间[begin1, end1)中搜索出与迭代器区间[begin2, end2)元素匹配的子序列,返回首元素的迭代器或begin1。
template<class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 find_end(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2
);
template<class ForwardIterator1, class ForwardIterator2, class Pr>
ForwardIterator1 find_end(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2,
BinaryPredicate _Comp
);
vector<int>::const_iterator iter;
vector<int>::iterator iLoaction;
iLoaction = find_end(v1.begin(), v1.end(), v2.begin(), v2.end());
if (iLoaction != v1.end())
{
cout << "v1中找到最后一个匹配V2的子序列,起始位置在:"
<< "v1[" << iLoaction - v1.begin() << "]" << endl;
}
7.count()
count算法用于计算容器中的某个给定值的出现次数。它有两个使用原型,均计算迭代器区间[begin, end)上等于value值的元素个数n,区别在于计数n是直接返回还是引用返回。
template<class InputIterator, class Type>
typename iterator_traits<InputIterator>::difference_type count(
InputIterator _First,
InputIterator _Last,
const Type& _Val
);
template<class InputIterator, class T> inline
size_t count(
InputIterator First,
InputIterator Last,
const T& Value
)
list<int> ilist;
int value = 9;
list<int>::difference_type num = 0; //difference_type用来表示两个迭代器之间的距离
num = count(ilist.begin(), ilist.end(), value);
cout << "链表中元素等于value的元素的个数:"<< num << endl;
string valString("is");
ptrdiff_t result = count(vecString.begin(), vecString.end(), valString);
cout << "容器中元素为is的元素个数:"
<< result << endl;
8.count_if()
count_if算法是使用谓词判断pred统计迭代器区间[first , last) 上满足条件的元素个数n,按计数n是否引用返回,有如下两种函数原型:
template<class InputIterator, class Predicate>
typename iterator_traits<InputIterator>::difference_type count_if(
InputIterator _First,
InputIterator _Last,
Predicate _Pred
);
template<class InputIterator, class T> inline
size_t count(
InputIterator First,
InputIterator Last,
const T& Value
)
bool setRange( pair<int, stuRI> s )
{
if (s.second.year > 20 && s.second.year < 30)
{
return true;
}
return false;
}
map<int, stuRI> m;
m.insert(make_pair(stu1.id, stu1.m_stuInfo));
m.insert(make_pair(stu2.id, stu2.m_stuInfo));
m.insert(make_pair(stu3.id, stu3.m_stuInfo));
m.insert(make_pair(stu4.id, stu4.m_stuInfo));
m.insert(make_pair(stu5.id, stu5.m_stuInfo));
//条件统计
int num = count_if(m.begin(), m.end(), setRange);
cout << "学生中年龄介于20至30之间的学生人数为:"<< num << endl;
9.mismatch()
mismatch算法是比较两个序列,找出首个不匹配元素的位置。它有如下两个函数原型,找出迭代器区间[begin1, end1) 上第一个元素 *i , 它和迭代器区间[begin2, begin2 + (end1 - begin1))上的元素* (begin2 + (i - begin1))不相等(或者不满足二元谓词binary_pred条件)。通过匹配对象pair返回这两个元素的迭代器,指示不匹配元素位置。
template<class InputIterator1, class InputIterator2>
pair<InputIterator1, InputIterator2> mismatch(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2
);
template<class InputIterator1, class InputIterator2, class BinaryPredicate>
pair<InputIterator1, InputIterator2> mismatch(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2
BinaryPredicate _Comp
);
bool strEqual(const char* s1, const char* s2)
{
return strcmp(s1, s2) == 0 ? true : false;
}
typedef vector<int>::iterator ivecIter;
pair<ivecIter, ivecIter> retCode;
retCode = mismatch(ivec1.begin(), ivec1.end(), ivec2.begin());
if (retCode.first == ivec1.end() && retCode.second == ivec2.end() /* ivec2.begin() */)
{
cout << "ivec1 和 ivec2完全相同" << endl;
}
else
{
cout << "ivec1 和 ivec2 不相同,不匹配的元素为:\n"
<< *retCode.first << endl
<< *retCode.second << endl;
}
char* str1[] = {"appple", "pear", "watermelon", "banana", "grape"};
char* str2[] = {"appple", "pears", "watermelons", "banana", "grape"};
pair<char**, char**> retCode2 = mismatch(str1, str1+5, str2, strEqual);
if (retCode2.first == str1+5 && retCode2.second == str2+5)
{
cout << "str1 和 str2 完全相同" << endl;
}
else
{
cout << "str1 和 str2 不相同,不匹配的字符串为:" << endl
<< str1[retCode2.first - str1] << endl
<< str2[retCode2.second - str2] << endl;
}
10.equal()
equal算法类似于mismatch,equal算法也是逐一比较两个序列的元素是否相等,只是equal函数的返回值为bool值true/false,不是返回迭代器值。它有如下两个原型,如果迭代器区间[begin1,end1)和迭代器区间[begin2, begin2+(end1 - begin1))上的元素相等(或者满足二元谓词判断条件binary_pred) ,返回true,否则返回false。
template<class InputIterator1, class InputIterator2>
bool equal(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2
);
template<class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
BinaryPredicate _Comp
);
bool absEqual(int a, int b)
{
return (a == abs(b) || b == abs(a)) ? true : false;
}
if ( equal( ivect1.begin(), ivect1.end(), ivect2.begin(), absEqual ) )
{
cout << "ivect1 和 ivect2 元素的绝对值完全相等" << endl;
}
else
{
cout << "ivect1 和 ivect2 元素的绝对值不完全相等" << endl;
}
11.search()
search算法函数在一个序列中搜索与另一序列匹配的子序列。它有如下两个原型,在迭代器区间[begin1, end1)上找迭代器区间[begin2, end2)完全匹配(或者满足二元谓词binary_pred)子序列,返回子序列的首个元素在[begin1, end1)区间的迭代器值,或返回end1表示没有匹配的子序列。
template<class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 search(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2
);
template<class ForwardIterator1, class ForwardIterator2, class Pr>
ForwardIterator1 search(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2
BinaryPredicate _Comp
);
vector<int>::iterator iterLocation;
iterLocation = search(v1.begin(), v1.end(), v2.begin(), v2.end());
if (iterLocation != v1.end())
{
cout << "v2的元素包含在v1容器中,起始元素为"<< "v1[" << iterLocation - v1.begin() << "]" <<endl;
}
else
{
cout << "v2的元素不包含在v1容器" << endl;
}
12.search_n()
重复元素子序列搜索search_n算法:搜索序列中是否有一系列元素值均为某个给定值的子序列,它有如下两个函数原型,分别在迭代器区间[begin, end)上搜索是否有count个连续元素,其值均等于value(或者满足谓词判断binary_pred的条件),返回子序列首元素的迭代器,或last以表示没有重复元素的子序列。
template<class ForwardIterator1, class Diff2, class Type>
ForwardIterator1 search_n(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
Size2 _Count,
const Type& _Val
);
template<class ForwardIterator1, class Size2, class Type, class BinaryPredicate>
ForwardIterator1 search_n(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
Size2 _Count,
const Type& _Val,
BinaryPredicate _Comp
);
bool twice(const int para1, const int para2)
{
return 2 * para1 == para2;
}
vector<int>::iterator iLocation;
iLocation = search_n(ivect.begin(), ivect.end(), 3, 8);
if (iLocation != ivect.end())
{
cout << "在ivect中找到3个连续的元素8" << endl;
}
else
{
cout << "在ivect中没有3个连续的元素8" << endl;
}
iLocation = search_n(ivect.begin(), ivect.end(), 4, 8);
if (iLocation != ivect.end())
{
cout << "在ivect中找到4个连续的元素8" << endl;
}
else
{
cout << "在ivect中没有4个连续的元素8" << endl;
}
iLocation = search_n(ivect.begin(), ivect.end(), 3, 16, twice);
if (iLocation != ivect.end())
{
cout << "在ivect中找到3个连续元素的两倍为16" << endl;
}
else
{
cout << "在ivect中没有3个连续元素的两倍为16" << endl;
}
13.copy()
元素复制算法copy,该算法主要用于容器之间元素的拷贝,即将迭代器区间[begin,end)的元素复制到由复制目标result给定的区间[result,result+(end-begin))中。
template<class InputIterator, class OutputIterator>
OutputIterator copy(
InputIterator _First,
InputIterator _Last,
OutputIterator _DestBeg
-);
int myints[] = {10, 20, 30, 40, 50, 60, 70};
vector<int> myvector;
//在这里一定要先为vector分配空间,否则程序会崩,这是初学者经常犯的一个错误。
myvector.resize(7);
//copy用法一:
//将数组myints中的七个元素复制到myvector容器中
copy ( myints, myints+7, myvector.begin() );
//copy用法二:
//将数组myints中的元素向左移动一位
copy(myints + 1, myints + 7, myints);
//copy用法三:
//输出容器里的所有元素,元素之间用空格隔开
cout << "Output : " << endl;
copy(myvector.begin(), myvector.end(), OstreamItr(cout, " "));
cout << endl;
14.copy_backward()
从最后的元素开始复制,直到首元素复制出来。也就是说,复制操作是从last-1开始,直到first结束。这些元素也被从后向前复制到目标容器中,从result-1开始,一直复制last-first个元素。
template<class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator2 copy_backward
(
BidirectionalIterator1 first,
BidirectionalIterator1 last,
BidirectionalIterator2 result
);
vector<int> myvector;
vector<int>::iterator iter;
myvector.resize( myvector.size()+3 );
copy_backward( myvector.begin(), myvector.begin()+2, myvector.end() );
//清除myvector容器
myvector.clear();
15.swap()
14.1 泛型算法swap
template <class T> void swap ( T& a, T& b )
{
T c(a); a=b; b=c;
}
int x = 10, y = 20; // x:10 y:20
swap(x, y);
14.2 容器中的成员函数swap
在容器vector中,其内存占用的空间是只增不减的,比如说首先分配了10,000个字节,然后erase掉后面9,999个,则虽然有效元素只有一个,但是内存占用仍为10,000个。所有内存空间在vector析构时回收。一般,我们都会通过vector中成员函数clear进行一些清除操作,但它清除的是所有的元素,使vector的大小减少至0,却不能减小vector占用的内存。要避免vector持有它不再需要的内存,这就需要一种方法来使得它从曾经的容量减少至它现在需要的容量,这样减少容量的方法被称为“收缩到合适(shrink
to fit)”。
vector< T >().swap(X)
int x = 10;
vector<int> myvector(10000, x);
//这里打印仅仅是元素的个数不是内存大小
cout << "myvector size:"
<< myvector.size()
<< endl;
//swap交换函数释放内存:vector<T>().swap(X);
//T:int ; myvertor代表X
vector<int>().swap(myvector);
//两个输出仅用来表示swap前后的变化
cout << "after swap :"<< myvector.size()<< endl;
swap交换技巧实现内存释放思想:vector()使用vector的默认构造函数建立临时vector对象,再在该临时对象上调用swap成员,swap调用之后对象myvector占用的空间就等于一个默认构造的对象的大小,临时对象就具有原来对象v的大小,而该临时对象随即就会被析构,从而其占用的空间也被释放。
std::vector<T>().swap(X)
作用相当于:
{
std::vector<T> temp(X);
temp.swap(X);
}
注意:并不是所有的STL容器的clear成员函数的行为都和vector一样。事实上,其他容器的clear成员函数都会释放其内存。比如另一个和vector类似的顺序容器deque。
16.iter_swap()
iter_swap该算法是通过迭代器来完成元素的交换。
template<class ForwardIterator1, class ForwardIterator2>
void iter_swap(
ForwardIterator1 _Left,
ForwardIterator2 _Right
);
deque<int> deq1;
//通过iter_swap算法交换队列中第一个和最后一个元素
iter_swap(deq1.begin() , --deq1.end());
// 通过iter_swap交换vector和deque两个不同容器中的元素
vector <int> v1;
deque <int> deq2;
//交换容器v1和队列deq2的第一个元素
iter_swap( v1.begin(), deq2.begin() );
17.swap_ranges()
swap_ranges是区间元素交换算法,该算法用于进行两个迭代器区间元素的交换。它的使用原形如下,将迭代器区间[begin1,end1)的元素,与迭代器区间[begin2,begin2+(end1-begin1))迭代器区间元素交换其中*begin1和*begin2交换、*(begin1+1)和*(begin2+1)交换、...*(end1-1)和*(begin2+ end1-begin1)-1)交换。
template<class ForwardIterator1, class ForwardIterator2>
ForwardIterator2 swap_ranges (
ForwardIterator1 first1,
ForwardIterator1 last1,
ForwardIterator2 first2
)
{
while (first1!=last1) swap(*first1++, *first2++);
return first2;
}
vector<int> first (5,10); // first: 10 10 10 10 10
vector<int> second (5,33); // second: 33 33 33 33 33
swap_ranges(first.begin()+1, first.end()-1, second.begin());
18.transform()
该算法用于实行容器元素的变换操作。有如下两个使用原型,一个将迭代器区间[begin,end)中元素,执行一元函数对象op操作,交换后的结果放在[result,result+(end-begin))区间中。另一个将迭代器区间[begin1,end1)的元素*i,依次与[begin2,begin2+(end-begin))的元素*j,执行二元函数操作binary_op(*i,*j),交换结果放在[result,result+(begin1-end1))。
template < class InputIterator, class OutputIterator, class UnaryOperator >
OutputIterator transform (
InputIterator first1,
InputIterator last1,
OutputIterator result,
UnaryOperator op
);
template < class InputIterator1, class InputIterator2,
class OutputIterator, class BinaryOperator >
OutputIterator transform (
InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
OutputIterator result,
BinaryOperator binary_op
);
int op_increase (int i) { return ++i; }
int op_sum (int i, int j) { return i+j; }
vector<int> first;
vector<int> second;
second.resize(first.size());
transform (first.begin(), first.end(), second.begin(), op_increase);
//第二个重载版本必须要保证两个容器的元素个数相等才行,否则会抛出异常。
transform (first.begin(), first.end(), second.begin(), first.begin(), op_sum);
19.replace()
replace 替换算法将指定元素值替换为新值,使用原型如下,将迭代器[first,last)中值为old_value的元素全部替换为new_value值。
template < class ForwardIterator, class T >
void replace (
ForwardIterator first,
ForwardIterator last,
const T& old_value,
const T& new_value
);
vector<int> myvector (myints, myints+8); // 10 20 30 30 20 10 10 20
replace (myvector.begin(), myvector.end(), 20, 99); // 10 99 30 30 99 10 10 99