C++里的通用算法

本文介绍了C++标准库中的通用算法及其在标准容器上的应用,并详细解释了如何使用谓词、约束器、适配器和否定器来增强算法的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  标准C++库里面提供了很多的通用算法,比如查找,排序等等, 这些算法完全建立在STL的基础上,是最先进算法的优良实现,有极好的性能, C库里的算法相比,一点也不逊色.

通常这些算法是对标准容器的操作,比如vector, list, map等等, 在用的时候非常灵活所有的算法包含在<algorithm>, 下面我会做一些典型的介绍.
首先是一段不用任何算法的代码:
int f(vector<int>& c)
{
 vector<int>::iterator it=c.begin(),end=c.end();
 while(it!=end)
 {
  if(*it<7)
   return*it;
 }
 return 0;
}
下面引入第一个算法:find_if
bool less_than_7(int v)
{
 return v<7;
}
int f2(vector<int>& c)
{
 vector<int>::iterator it=find_if(c.begin(),c.end(),less_than_7);
 if(it!=c.end())
  return *it;
 return 0;
}
less_than_7是我们编写的一个函数, 用于算法find_if. 算法的作用是找到vector里所有的元素小于的序列. 请看另外一个实现相同功能的方式:函数对象.
函数对象, 如果一个类具有应用运算符,我们就称其为函数对象.
 class less_than
{
public:
 less_than(int i=0):v(i){}
 bool operator()(int x){return x<v;}
private:
 int v;
};
int f3(vector<int>& c)
{
 less_than les(7);
 vector<int>::iterator it=find_if(c.begin(),c.end(),les);
 if(it!=c.end())
  return *it;
 return 0;
}
这里我们换成一个类, 比较的值可以传进类里, 实现了更大的灵活性. 进一步, 我们把比较的值的类型抽象, 把函数对象变为模板:
 template<class T>
class less_than
{
public:
 less_than(T i=0):v(i){}
 bool operator()(T x){return x<v;}
private:
 T v;
};
int f3(vector<int>& c)
{
 less_than<int> les(7);
 vector<int>::iterator it=find_if(c.begin(),c.end(),les);
 if(it!=c.end())
  return *it;
 return 0;
}
less_than这样的对象我们经常用到,那么有没有库里实现好的,我们直接拿来用的呢?有的!下面我们介绍基本的谓词:
谓词就是返回bool的函数或函数对象.
void f4(vector<int>& vi,list<int>& li)
{
 typedef list<int>::iterator LI;
 typedef vector<int>::iterator VI;
 pair<VI,LI> pl=mismatch(vi.begin(),vi.end(),li.begin(),greater_equal<int>());
 ...
}
greater_equal就是库里的一个常用谓词: return arg1>=arg2, mismatch也是库里的算法, 意思是找到两个序列相异的第一个元素.在这里就是寻找vector中小于在list中对应元素的第一个元素.
<functional>,标准库里提供了一些常用的谓词,:equal_to, less, greater,当然我们也可以开发自己的谓词, 比如下面一个:
Class MyEqual:public unary_function<Teacher,bool>{
      String s;
    Public:
       MyEqual(const string& str):s(str) {}
       Bool operator() (const Teacher & t) const {return t.name==s;}
};
List<Teacher> li;
List<Teacher>::iterator it=find_if(li.begin(),li.end(),MyEqual(“张三”));
上面代码的功能是找到教师序列里名字为张三的老师.其中unary_function是所有一元谓词对象的基类.
约束器,通过将一个参数约束到某个值,我们可以将两个参数的函数对象当作一个参数的函数对象使用.
对于上面的例子:
 less_than les(7);
 vector<int>::iterator it=find_if(c.begin(),c.end(),les);
less_than是我们额外写的一个类, 如果我们不想写自己的类, 而直接利用库里的谓词less,这样岂不是更好吗? 约束器就是满足这种需求:
vector<int>::iterator it=find_if(c.begin(),c.end(),bind2nd(less<int>(),7);
bind2nd就是一个常用的约束器,它把二元谓词less和常数7出发建立起一元谓词小于7”.
 
成员函数适配器, 使成员函数可以被用做算法参数.
void draw_all(list<Shape*>& lsp)
{
      for_each(lsp.begin(),lsp.end(),mem_fun(&Shape::draw));
}
这里是通过指针调用成员函数的,如果需要参数,那么我们就可以用到前面讲的bind2nd:
void draw_all(list<Shape*>& lsp,int angle)
{
for_each(lsp.begin(),lsp.end(),bind2nd(mem_fun(&Shape::rotate),angle));
}
 
函数指针适配器, 使函数适指针可以用作算法参数.
void draw(const int angle);
void draw_all(list<Shape*>& lsp)
{
      for_each(lsp.begin(),lsp.end(),bind2nd(ptr_fun(draw),30));
}
否定器,描述某个谓词的否定.
void f7(vector<int>& vi,list<int> li)
{
      pi=mismatch(vi.begin(),vi.end(),li.begin(),not2(less<int>()));
}
谓词,约束器,适配器和否定器都定义在<functional>.有些一下子看起来比较生僻,这是一个习惯问题, 你熟悉了,也就觉得很自然了.而且这些都在标准库里, 可移植性都很高.
这里只是介绍一些基本的入门知识, 通过这些初步的代码,我们知道算法可以节省我们大量的精力,避免我们为这些常见的算法一再的去重复劳动, 而且代码更精简.
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值