标准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> . 有些一下子看起来比较生僻 , 这是一个习惯问题 , 你熟悉了 , 也就觉得很自然了 . 而且这些都在标准库里 , 可移植性都很高 .
这里只是介绍一些基本的入门知识 , 通过这些初步的代码 , 我们知道算法可以节省我们大量的精力 , 避免我们为这些常见的算法一再的去重复劳动 , 而且代码更精简 .
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐