目录
比较算法:Lexicographical_compare()
复制算法系列:unique_copy()&remove_copy()&remove_copy_if()©_backward()
常用STL算法
算法简介
查找、搜索、删除和计数是一些通用算法,其应用范围很广。STL通过通用的模板函数提供了这些算法以及其他的很多算法,可通过迭代器对容器进行操作。要使用STL算法,程序员必须包含头文件<algorithm>。STL算法分两大类:非变序算法与变序算法。
非变序算法
不改变容器中元素的顺序和内容的算法称为非变序算法:
变序算法
变序算法改变其操作的序列的元素顺序或内容:
算法示例
计数算法
函数原型
typename iterator_traits<InputIterator>::difference_type count (InputIterator first, InputIterator last, const T& val) |
typename iterator_traits<InputIterator>::difference_type count_if (InputIterator first, InputIterator last, UnaryPredicate pred) |
参数解析
Count()函数的作用是“用来计数数组中特定元素的个数”;
Count_if()函数的作用是“用来计数数组中满足条件的元素的个数”。
代码示例
// STL算法.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
struct Student
{
float mark;
string name;
Student(string name, float mark)
{
this->mark = mark;
this->name = name;
}
bool operator == (const Student& stud)
{
return this->name == stud.name;
}
};
int main()
{
Student stud1("张三", 77.5), stud2("李四", 88.3), stud3("王五", 91.2);
vector<Student> VectorArray{ stud1,stud2,stud3 };
int CommonNumber = count(VectorArray.begin(), VectorArray.end(), stud1);
cout << "stud1共出现的次数为" << CommonNumber << endl;
int TheObject = count_if(VectorArray.begin(), VectorArray.end(), [](Student& stud) {return stud.mark >= 80; });
cout << "学生成绩大于80的人数为" << TheObject << endl;
}
// 注意返回值类型是“无符号整型”
搜索算法:Search()
函数原型
ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) |
ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred) |
参数解析
Search()函数与find()函数作用相同,但是find()函数是查找符合条件的一个元素的地址,但是search()函数是查找符合条件的子序列的首地址。
代码示例
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
struct Student
{
float mark;
string name;
Student(string name, float mark)
{
this->mark = mark;
this->name = name;
}
bool operator == (const Student& stud)
{
return this->name == stud.name;
}
friend ostream& operator << (ostream& Output, const Student& stud);
};
ostream& operator << (ostream& Output, const Student& stud)
{
Output << stud.name << "的成绩为" << stud.mark << endl;
return Output;
}
int main()
{
Student stud1("张三", 77.5), stud2("李四", 88.3), stud3("王五", 91.2);
vector<Student> VectorArray{ stud1,stud2,stud3 }, VectorArray1{ stud1,stud2 };
vector<Student>::iterator itor = search(VectorArray.begin(), VectorArray.end(), VectorArray1.begin(), VectorArray1.end(), [](Student& stud1, Student& stud2) {return stud1.mark != stud2.mark; });
cout << *itor << endl; // itor代表了在VectorArray中VectorArray1子序列第一次出现的起始地址
}
// 注意:这里search有5个元素,代表着“查找一个子序列(条件是:VectorArray子序列必须与VectorArray1的元素不相等)的头地址”
搜索算法:Search_n()
函数原型
ForwardIterator search_n (ForwardIterator first, ForwardIterator last, Size count, const T& val); |
ForwardIterator search_n ( ForwardIterator first, ForwardIterator last, Size count, const T& val, BinaryPredicate pred ); |
参数解析
这个函数与find_first_of()用法很相近,只不过这里的第二个子序列是由count个val组成的重复子序列,同样这里的等价条件pred也可以自定义。
代码示例
// search_n example
#include <iostream> // std::cout
#include <algorithm> // std::search_n
#include <vector> // std::vector
bool mypredicate (int i, int j) {
return (i==j);
}
int main () {
int myints[]={10,20,30,30,20,10,10,20};
std::vector<int> myvector (myints,myints+8);
std::vector<int>::iterator it;
// using default comparison:
it = std::search_n (myvector.begin(), myvector.end(), 2, 30);
if (it!=myvector.end())
std::cout << "two 30s found at position " << (it-myvector.begin()) << '\n';
else
std::cout << "match not found\n";
// using predicate comparison:
it = std::search_n (myvector.begin(), myvector.end(), 2, 10, mypredicate);
if (it!=myvector.end())
std::cout << "two 10s found at position " << int(it-myvector.begin()) << '\n';
else
std::cout << "match not found\n";
return 0;
}
// 注意:这里有5个元素的search_n是查找与{10,10}序列满足mypredicate关系的第首地址
搜索算法:Find_first_of()函数
函数原型
ForwardIterator1 find_first_of (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) |
ForwardIterator1 find_first_of (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred) |
参数解析
Find_first_of()函数的目的是求解“满足pred条件的[first2,last2)子序列在[first1,last1)出现的首地址”。
代码示例
// find_first_of example
#include <iostream> // std::cout
#include <algorithm> // std::find_first_of
#include <vector> // std::vector
#include <cctype> // std::tolower
bool comp_case_insensitive (char c1, char c2) {
return (std::tolower(c1)==std::tolower(c2));
}
int main () {
int mychars[] = {'a','c','c','A','C','C'};
std::vector<char> haystack (mychars,mychars+6);
std::vector<char>::iterator it;
int needle[] = {'A','B','C'};
// using default comparison:
it = find_first_of (haystack.begin(), haystack.end(), needle, needle+3);
if (it!=haystack.end())
std::cout << "The first match is: " << *it << '\n'; // ‘A’
// using predicate comparison:
it = find_first_of (haystack.begin(), haystack.end(),
needle, needle+3, comp_case_insensitive);
if (it!=haystack.end())
std::cout << "The first match is: " << *it << '\n'; // ‘a’
return 0;
}
// 注意:这个函只查找第二个序列中第一个元素在第一个序列中满足条件的的位置
搜索算法:Adjacent_find()
函数原型
ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last) |
ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last, BinaryPredicate pred) |
参数解析
在adjacent_find()函数中,有一个predicate参数,这个参数是让我们自定义“满足什么条件两个元素才算等价”。如果不添加第5个参数,那么会使用系统默认的“等价条件”来挑选出数组中第一个相邻等价元素的首地址。
代码示例
// adjacent_find example
#include <iostream> // std::cout
#include <algorithm> // std::adjacent_find
#include <vector> // std::vector
bool myfunction (int i, int j) {
return (i==j);
}
int main () {
int myints[] = {5,20,5,30,30,20,10,10,20};
std::vector<int> myvector (myints,myints+8);
std::vector<int>::iterator it;
// using default comparison:
it = std::adjacent_find (myvector.begin(), myvector.end());
if (it!=myvector.end())
std::cout << "the first pair of repeated elements are: " << *it << '\n';
//using predicate comparison:
it = std::adjacent_find (++it, myvector.end(), myfunction);
if (it!=myvector.end())
std::cout << "the second pair of repeated elements are: " << *it << '\n';
return 0;
}
比较算法:Equal()
函数原型
bool equal (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) |
bool equal (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred) |
参数解析
比较范围[first1,last1)中的元素和从first2开始的元素,如果两个范围中的所有元素都匹配,则返回true而且我们可以自定义匹配的条件pred。
代码示例
// equal algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::equal
#include <vector> // std::vector
bool mypredicate (int i, int j) {
return (i==j);
}
int main () {
int myints[] = {20,40,60,80,100}; // myints: 20 40 60 80 100
std::vector<int>myvector (myints,myints+5); // myvector: 20 40 60 80 100
// using default comparison:
if ( std::equal (myvector.begin(), myvector.end(), myints) )
std::cout << "The contents of both sequences are equal.\n";
else
std::cout << "The contents of both sequences differ.\n";
myvector[3]=81; // myvector: 20 40 60 81 100
// using predicate comparison:
if ( std::equal (myvector.begin(), myvector.end(), myints, mypredicate) )
std::cout << "The contents of both sequences are equal.\n";
else
std::cout << "The contents of both sequences differ.\n";
return 0;
}
比较算法:equal_range()
函数原型
pair<ForwardIterator,ForwardIterator> equal_range (ForwardIterator first, ForwardIterator last, const T& val) |
pair<ForwardIterator,ForwardIterator> equal_range (ForwardIterator first, ForwardIterator last, const T& val, Compare comp) |
参数解析
返回子序列(子序列是由若干个val重复元素构成)在主序列中的边界地址,该地址范围包括子序列的所有元素。但是返回的边界地址是[主序列中子序列第一个元素的地址,主序列中子序列最后一个元素的后一个元素的地址),我们要注意地址区间是“左闭右开的”,因此在这个地址范围内包含子序列中的所有元素。
代码示例
// equal_range example
// equal_range example
#include <iostream> // std::cout
#include <algorithm> // std::equal_range, std::sort
#include <vector> // std::vector
bool mygreater (int i,int j) { return (i>j); }
int main () {
int myints[] = {10,20,30,30,20,10,10,20};
std::vector<int> v(myints,myints+8); // 10 20 30 30 20 10 10 20
std::pair<std::vector<int>::iterator,std::vector<int>::iterator> bounds;
// using default comparison:
std::sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30
bounds=std::equal_range (v.begin(), v.end(), 20); // ^ ^
// using "mygreater" as comp:
std::sort (v.begin(), v.end(), mygreater); // 30 30 20 20 20 10 10 10
bounds=std::equal_range (v.begin(), v.end(), 20, mygreater); // ^ ^
std::cout << "bounds at positions " << (bounds.first - v.begin());
std::cout << " and " << (bounds.second - v.begin()) << '\n';
return 0;
}
比较算法:mismatch()
函数原型
pair<InputIterator1, InputIterator2> mismatch (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) |
pair<InputIterator1, InputIterator2> mismatch (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred) |
参数解析
比较范围[first1,last1)中的元素和从first2开始的元素,并返回两个序列中不匹配的第一个元素。Pred是用来自定义匹配条件的。
代码示例
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
vector<int> VectorArray1{ 10,20,30,40,50 }, VectorArray2{ 10,20,31,40,50 };
pair<vector<int>::iterator, vector<int>::iterator> PairItor = mismatch(VectorArray1.begin(), VectorArray1.end(), VectorArray2.begin(), [](int& var1, int& var2) {return var1 == var2; });
cout << "主数组中的第一个不匹配元素是" << *PairItor.first << endl;
cout << "子序列中第一个不匹配的元素是" << *PairItor.second << endl;
}
比较算法:Lexicographical_compare()
函数原型
bool lexicographical_compare (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) |
bool lexicographical_compare (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp) |
参数解析
Lexicographical_compare()是一种比较,通常用于字典中按字母顺序对单词进行排序;它包括按顺序比较在两个范围内具有相同位置的元素,直到其中一个元素与另一个元素不相等。比较第一个不匹配元素的结果就是字典比较的结果。
如果两个序列相等,直到其中一个结束,则较短的序列在字典上小于较长的序列。Comp用以自定义比较规则。
代码示例
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct Student
{
string name;
float mark;
Student(string name, float mark)
{
this->name = name;
this->mark = mark;
}
bool operator > (const Student& stud)
{
return this->mark > stud.mark;
}
bool operator < (const Student& stud)
{
return this->mark < stud.mark;
}
bool operator == (const Student& stud)
{
return this->mark == stud.mark;
}
};
int main()
{
Student stud1("张三", 81.4), stud2("李四", 83.6), stud3("王五", 93);
vector<Student> VectorArray1{ stud1,stud3 }, VectorArray2{ stud1,stud2 };
bool CompareArray = lexicographical_compare(VectorArray1.begin(), VectorArray1.end(), VectorArray2.begin(), VectorArray2.end());
cout << CompareArray << endl; // true-VectorArray1小于VectorArray2
}
初始化算法:fill()
函数原型
void fill (ForwardIterator first, ForwardIterator last, const T& val) |
参数解析
将指定值val分配给指定范围[frst,last)中的每个元素,注意区间的范围是“左闭右开”。
代码示例
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
struct Student
{
string name;
float mark;
Student() {};
Student(string name, float mark)
{
this->name = name;
this->mark = mark;
}
};
int main()
{
Student stud1("张三", 87.2), stud2("李四", 88.6), stud3("王五", 90);
vector<Student> stud(3); // 预留空间
fill(stud.begin(), stud.end(), stud1);
stud.clear(); stud.resize(3); // 清楚元素后重新申请空间
fill_n(stud.begin(), 3, stud1);
}
初始化算法:fill_n()
函数原型
OutputIterator fill_n (OutputIterator first, Size n, const T& val) |
参数解析
将val赋给由first指向的序列的前n个元素。
代码示例
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
struct Student
{
string name;
float mark;
Student() {};
Student(string name, float mark)
{
this->name = name;
this->mark = mark;
}
};
int main()
{
Student stud1("张三", 87.2), stud2("李四", 88.6), stud3("王五", 90);
vector<Student> stud(3); // 预留空间
fill(stud.begin(), stud.end(), stud1);
stud.clear(); stud.resize(3); // 清楚元素后重新申请空间
fill_n(stud.begin(), 3, stud1);
}
初始化算法:generate()&generate_n()
函数原型
void generate (ForwardIterator first, ForwardIterator last, Generator gen) |
OutputIterator generate_n (OutputIterator first, Size n, Generator gen) |
参数解析
Generate() |
将连续调用gen返回的值赋给范围内的元素[first,last) |
Generate_n() |
将连续调用gen返回的值赋给由first指向的序列的前n个元素,返回值为一个迭代器,它指向最后一个生成其值的元素之后的元素。 |
注意:generate_n()中的参数gen无形参,初始化函数的本意就是不依赖于任何数组内的参数向数组内装填数据。
代码示例
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
struct Student
{
string name;
float mark;
Student() {};
Student(string name, float mark)
{
this->name = name;
this->mark = mark;
}
friend ostream& operator << (ostream& Output, Student& stud);
};
ostream& operator << (ostream& Output, Student& stud)
{
Output << stud.name << "的成绩为" << stud.name;
return Output;
}
int main()
{
Student stud1("张三", 87.2), stud2("李四", 88.6), stud3("王五", 90);
vector<Student> stud(3); // 预留空间
fill(stud.begin(), stud.end(), stud1);
stud.clear(); stud.resize(3); // 清楚元素后重新申请空间
fill_n(stud.begin(), 3, stud1);
stud.clear(); stud.resize(3);
generate(stud.begin(), stud.end(), [&stud1]()mutable {return stud1; }); // 对范围内的每个元素调用lambda函数
stud.clear(); stud.resize(3);
vector<Student>::iterator itor = generate_n(stud.begin(), 3, [&stud1]()mutable {return stud1; }); // 对范围内的每个元素调用lambda函数
if (itor == stud.end())
{
cout << "迭代器指向generate_n()装填序列末尾元素的后一个元素" << endl;
}
}
运行结果
修改算法:for_each()
函数原型
Function for_each (InputIterator first, InputIterator last, Function fn) |
参数解析
对指定范围内的每个元素执行指定的操作。当指定的参数修改了范围时,for_each将是变序算法
代码示例
// for_each example
#include <iostream> // std::cout
#include <algorithm> // std::for_each
#include <vector> // std::vector
void myfunction (int i) { // function:
std::cout << ' ' << i;
}
struct myclass { // function object type:
void operator() (int i) {std::cout << ' ' << i;}
} myobject;
int main () {
std::vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
std::cout << "myvector contains:";
for_each (myvector.begin(), myvector.end(), myfunction);
std::cout << '\n';
// or:
std::cout << "myvector contains:";
for_each (myvector.begin(), myvector.end(), myobject);
std::cout << '\n';
return 0;
}
结果展示
修改算法:transform()
函数原型
OutputIterator transform (InputIterator first1, InputIterator last1, OutputIterator result, UnaryOperation op) |
OutputIterator transform (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binary_op) |
参数解析
按顺序对数组1或数组2范围的元素应用操作,并将结果存储在从result开始的范围内。
代码示例
// transform algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::transform
#include <vector> // std::vector
#include <functional> // std::plus
int op_increase (int i) { return ++i; }
int main () {
std::vector<int> foo;
std::vector<int> bar;
// set some values:
for (int i=1; i<6; i++)
foo.push_back (i*10); // foo: 10 20 30 40 50
bar.resize(foo.size()); // allocate space
std::transform (foo.begin(), foo.end(), bar.begin(), op_increase);
// bar: 11 21 31 41 51
// std::plus adds together its two arguments:
std::transform (foo.begin(), foo.end(), bar.begin(), foo.begin(), std::plus<int>());
// foo: 21 41 61 81 101
std::cout << "foo contains:";
for (std::vector<int>::iterator it=foo.begin(); it!=foo.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
数组中resize与reserve的区别
Reserve |
函数分配出来的内存空间,只是表示vector可以利用这部分内存,但vector不能有效地访问这些内存空间,访问的时候就会出现越界现象,导致程序崩溃 |
Resize |
函数重新分配大小,改变容器的大小,并且可以创建对象 void resize (size_type n); void resize (size_type n, value_type val); |
复制算法系列:unique_copy()&remove_copy()&remove_copy_if()©_backward()
函数原型
OutputIterator unique_copy (InputIterator first, InputIterator last, OutputIterator result) |
OutputIterator unique_copy (InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate pred) |
BidirectionalIterator2 copy_backward (BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result) |
OutputIterator remove_copy_if (InputIterator first, InputIterator last, OutputIterator result, UnaryPredicate pred) |
OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, const T& val) |
参数解析
Unique_copy():将源范围内的所有元素复制到目标范围,但相邻的重复元素除外。只复制范围[first,last)中每个连续的等效元素组中的第一个元素。
Remove_copy_if()&remove_copy():
Copy_backward():
代码示例
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
struct Student
{
string name;
float mark;
Student() // 好习惯:给未赋初值的Student对象一个特定的值
{
this->name = "空";
this->mark = 0;
}
Student(string name, float mark)
{
this->name = name;
this->mark = mark;
}
bool operator == (const Student& stud)
{
return this->name == stud.name;
}
bool operator > (const Student& stud)
{
return this->mark > stud.mark;
}
friend ostream& operator << (ostream& Output, const Student& stud);
};
ostream& operator << (ostream& Output, const Student& stud)
{
Output << stud.name << "的成绩为" << stud.mark; // 不可以加endl清除缓冲区
return Output;
}
int main()
{
Student stud1("张三", 89), stud2("李四", 91.2), stud3("王五", 83), stud4("赵六", 98.3);
vector<Student> VectorArray1{ stud1,stud2,stud3,stud4 }, VectorArray2(VectorArray1.size()), VectorArray3(VectorArray1.size());
remove_copy(VectorArray1.begin(), VectorArray1.end(), VectorArray2.begin(), stud1); // 将数组1中除stud1之外的元素copy到数组2中
VectorArray2.resize(VectorArray1.size() - count(VectorArray1.begin(), VectorArray1.end(), stud1));
remove_copy_if(VectorArray1.begin(), VectorArray1.end(), VectorArray2.begin(), [](const Student& stud) {return stud.mark > 90; });
// 将数组1中满足条件的元素copy到数组2中
copy_backward(VectorArray1.begin(), VectorArray1.end(), VectorArray3.end()); // 将数组1中的元素倒序装入数组2中
VectorArray2.push_back(stud1); VectorArray2.insert(VectorArray2.begin(), stud1);
VectorArray3.clear(); VectorArray3.resize(VectorArray2.size()); // 清空数组3并且申请空间
unique_copy(VectorArray2.begin(), VectorArray2.end(), VectorArray3.begin()); // 相邻相同元素仅保留一个
}