C++泛型算法中常用函数

来源:互联网 发布:dijkstra算法详解 编辑:程序博客网 时间:2024/06/08 02:41

所谓泛型算法

实际上就是一系列通用的操作,这些操作大多数独立于任何特定的容器,是通用的,所以叫做泛型算法。
泛型算法包含的非常多,这里只记一些基本的操作。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;}
0 0
原创粉丝点击