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

所谓泛型算法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值