所谓泛型算法
实际上就是一系列通用的操作,这些操作大多数独立于任何特定的容器,是通用的,所以叫做泛型算法。
泛型算法包含的非常多,这里只记一些基本的操作。lambda表达式,闭包操作操作和其他迭代器以及配合使用的操作,后序再记录。
查找:
find函数用来查找一定范围内的一个元素,数据有序无序都可以,如果要查找的类型不是基本数据类型,需要重载运算符==
find函数的源码如下,很好理解。
template<class InputIterator, class T>
InputIterator find (InputIterator first, InputIterator last, const T& val)
{
while (first!=last) {
if (*first==val) return first;
++first;
}
return last;
}
三种例子,分别是查找数组,查找容器,查找自己定义的类型
代码来自cpp官网,修改过
#include <bits/stdc++.h>
using namespace std;
struct node
{
int x;
bool operator == (const node &n) const {return this->x==n.x;}
};
int main()
{
ios::sync_with_stdio(false);
//使用指针
int myints[]={ 10, 20, 30, 40 };
int* p;
p=find(myints, myints+4, 30);
if(p!=myints+4)
cout<<*p<<endl;
//或者可以这样
auto pp=find(begin(myints),end(myints),30);//返回的是一个指针
if(pp!=end(myints))
cout<<*pp<<endl;
// 使用迭代器
vector<int> myvector (myints,myints+4);
vector<int>::iterator it;
it=find(myvector.begin(), myvector.end(), 30);
if(it!=myvector.end())
cout<<*it<<'\n';
//自己定义的类型
vector<node> ve;
for(int i=0;i<10;i++)
ve.push_back(node{i});
node mark;
mark.x=3;
auto pos=find(ve.begin(),ve.end(),mark);
if(pos!=ve.end())
cout<<pos->x<<endl;
return 0;
}
查找函数还有lower_bound、binary_search等函数,后序记录。
排序:
c++中最经常使用的算法应该就是排序算法,也就是sort函数。当然还有有partial_sort
以及stable_sort,并不常用,后序介绍。
sort函数排序默认是从小到大,如果想给自定义类型排序,可以重载运算符或者自定义比较函数。
#include <bits/stdc++.h>
using namespace std;
bool myfunction (int i,int j) { return (i<j); }
struct myclass
{
bool operator() (int i,int j) { return (i<j);}
} myobject;
int main ()
{
ios::sync_with_stdio(false);
int myints[] = {32,71,12,45,26,80,53,33};
//不使用迭代器给数组排序
sort(begin(myints),end(myints));
//或者如下,效果相同
sort(myints,myints+8);
//如果使用迭代器,那么最好放在容器当中操作
std::vector<int> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33
// using default comparison (operator <):
std::sort (myvector.begin(), myvector.begin()+4); //(12 32 45 71)26 80 53 33
// using function as comp
std::sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)
// using object as comp
std::sort (myvector.begin(), myvector.end(), myobject); //(12 26 32 33 45 53 71 80)
return 0;
}
去重:
unique的作用是剔除相邻元素之间的重复元素。
unique函数可以实现在排好序的情况对数据进行去重,如果是自定义类型,需要重载运算符。
不过unique的去重并不是真正的删除重复的元素,而是把重复的元素放到后面,配合erase函数可以起到去重重复元素的作用。
源码如下(很经典哦,面试的时候一般都喜欢出这样的,呵呵)
template <class ForwardIterator>
ForwardIterator unique (ForwardIterator first, ForwardIterator last)
{
if (first==last) return last;
ForwardIterator result = first;
while (++first != last)
{
if (!(*result == *first)) // or: if (!pred(*result,*first)) for version (2)
*(++result)=*first;
}
return ++result;
}
例子:
代码来自cpp官网
#include <bits/stdc++.h>
using namespace std;
bool myfunction (int i, int j) {
return (i==j);
}
int main ()
{
ios::sync_with_stdio(false);
int myints[] = {10,20,20,20,30,30,20,20,10}; // 10 20 20 20 30 30 20 20 10
std::vector<int> myvector (myints,myints+9);
// using default comparison:
std::vector<int>::iterator it;
//把相邻的重复元素都移到后面去了
it = std::unique (myvector.begin(), myvector.end()); // 10 20 30 20 10 ? ? ? ?
// ^
//distance函数是计算两个迭代器之间的距离,算出后用resize重新分配内存达到删除重复的目的
myvector.resize( std::distance(myvector.begin(),it) ); // 10 20 30 20 10
// 自定义操作
std::unique (myvector.begin(), myvector.end(), myfunction); // (no changes)
// print out content:
std::cout << "myvector contains:";
for (it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
简单的去重代码
#include <bits/stdc++.h>
using namespace std;
int main ()
{
ios::sync_with_stdio(false);
vector<int> ve={1,2,3,4,2,4,1,3};
sort(ve.begin(),ve.end());
auto end_it=unique(ve.begin(),ve.end());
ve.erase(end_it,ve.end());
for(auto x:ve)
cout<<x<<endl;
return 0;
}
累加:
accumulate函数可以实现对一组能够累加的数据进行累加操作,如果用户重载了运算符,也可以进行类似操作。用户还可以添加自定义的函数操作,用来实现不同方式的累加。
源码如下,其中init为初始值
template <class InputIterator, class T>
T accumulate (InputIterator first, InputIterator last, T init)
{
while (first!=last) {
init = init + *first; // or: init=binary_op(init,*first) for the binary_op version
++first;
}
return init;
}
用例,代码来自cpp官网
#include <bits/stdc++.h>
using namespace std;
int myfunction (int x, int y) {return x+2*y;}
struct myclass {
int operator()(int x, int y) {return x+3*y;}
} myobject;
int main ()
{
ios::sync_with_stdio(false);
int init = 100;
int numbers[] = {10,20,30};
std::cout << "using default accumulate: ";
std::cout << std::accumulate(numbers,numbers+3,init);//160
std::cout << '\n';
std::cout << "using functional's minus: ";
//累减
std::cout << std::accumulate (numbers, numbers+3, init, std::minus<int>());//40
std::cout << '\n';
std::cout << "using custom function: ";
std::cout << std::accumulate (numbers, numbers+3, init, myfunction);//220
std::cout << '\n';
std::cout << "using custom object: ";
std::cout << std::accumulate (numbers, numbers+3, init, myobject);//280
std::cout << '\n';
return 0;
}
赋值:
fill函数可以可以向容器当中的一定范围能赋值,一共接受3个参数,类似于memset函数。
源码如下
template <class ForwardIterator, class T>
void fill (ForwardIterator first, ForwardIterator last, const T& val)
{
while (first != last) {
*first = val;
++first;
}
}
使用例子,非常简单
#include <bits/stdc++.h>
using namespace std;
int main ()
{
ios::sync_with_stdio(false);
std::vector<int> myvector (8); // myvector: 0 0 0 0 0 0 0 0
std::fill (myvector.begin(),myvector.begin()+4,5); // myvector: 5 5 5 5 0 0 0 0
std::fill (myvector.begin()+3,myvector.end()-2,8); // myvector: 5 5 5 8 8 8 0 0
return 0;
}
同样还有一个fill_n函数,与fill函数不同的是,它接收的参数。它接受的三个参数不是范围
OutputIterator fill_n (OutputIterator first, Size n, const T& val);
first为起始地址,n表示从first开始到后面的n-1个数被赋值成val,如果n的范围超过容器的大小,会出现未定义的行为!
源码如下
template <class OutputIterator, class Size, class T>
OutputIterator fill_n (OutputIterator first, Size n, const T& val)
{
while (n>0) {
*first = val;
++first; --n;
}
return first; // since C++11
}
使用例子
代码来自cpp官网
#include <bits/stdc++.h>
using namespace std;
int main ()
{
ios::sync_with_stdio(false);
std::vector<int> myvector (8,10); // myvector: 10 10 10 10 10 10 10 10
std::fill_n (myvector.begin(),4,20); // myvector: 20 20 20 20 10 10 10 10
std::fill_n (myvector.begin()+3,3,33); // myvector: 20 20 20 33 33 33 10 10
return 0;
}
复制:
copy函数接受三个参数
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result);
first和last表示复制数据的范围,result表示被赋值容器的起始位置,这里被赋值的容器大小至少要和[first,last)长度相同。
源码:
template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last) {
*result = *first;
++result; ++first;
}
return result;
}
使用例子
代码来自cpp官网
#include <bits/stdc++.h>
using namespace std;
int main ()
{
ios::sync_with_stdio(false);
int myints[]={10,20,30,40,50,60,70};
std::vector<int> myvector (7);
std::copy (myints, myints+7, myvector.begin());
//书上的例子
int a1[]={1,2,3,4,5};
int a2[sizeof(a1)/sizeof(*a1)];//a2与a1一样大小
auto ret=copy(begin(a1),end(a1),a2);
//ret返回为a2赋值的结尾
return 0;
}