其它算法

现在总结一下我们学习了哪些 STL 算法。首先,我们以 rg::sortrg::copy 这两个常用的算法作为引入,了解了 STL(主要是 STLv2)的基本使用方法。其次,我将话题转向函数式思想的常用方法:用作筛选的 rg::copy_ifstd::views::filter、用作转换的 rg::transformstd::views::transform,以及用作归约的 std::accumulatestd::reduce。此外,还有如 std::views::take 、输入输出迭代器/视图等辅助工具帮我们写出更好的代码。

但 STL 算法实在是太多了,我也不希望在这里把它们全部讲完。当初我的老师直接把 STLv1 的所有算法函数念了一遍,两三个小时学生啥也记不住。这样做是没有太多意义的。

首先,我按照通常的习惯把 STL 算法分成若干类:

  • 检查式的算法:它们检查一个范围内的元素,不修改它们也不会生成新的元素。
  • 生成元素的算法:它们会生成一些新的元素;调用的时候一般需要提供目的地迭代器。
  • 修改元素的算法:它们会将范围内的元素值修改掉。这其中又包括:
    • 简单算法:如覆盖、反转等;
    • 删除算法:如 rg::remove rg::unique 等。它们一般需要配合容器的 erase 方法使用。
    • 高级算法:排序、排列等。
  • 在已排序范围上的算法:主要包括二分搜索和集合运算。严格上它们属于修改元素的算法,但它们自成体系,故单独列出。
  • 惰性算法:即视图和对应的范围适配器。

CppReferenceopen in new window 里列出了所有的 STL 算法。上面的分类完全是个人意见;如果你有更好的看法请告诉我。

接下来我再介绍一些常用的算法。

删除算法

之前介绍筛选算法时,提到了筛选出的元素应该如何存放的问题。当时给出了两个方案:一是 rg::copy_if,将元素选择性地复制到新的地方。这对应了刚刚分类里的“生成元素的算法”。二是使用范围适配器,即刚刚分类里的“惰性算法”。但还有第三种可能:直接原地修改原来容器里的元素——也就是“修改元素的算法”。

简单算法

简单算法指一句话就能带过的算法

  • rg::fill 将一个范围填充为单个元素。使用方法如 rg::fill(a, 0)
  • rg::reverse 将一个双向范围内的元素反转。使用方法如 rg::reverse(a)
  • rg::shuffle 将随机访问范围内的元素随机重排(洗牌)。使用方法如 rg::shuffle(a, g);其中 g伪随机数生成引擎
  • rg::rotate 将前向范围内的元素 旋转。所谓旋转是指,将每个元素都向左平移一定长度,然后让头部元素移到尾部。使用方法如 rg::rotate(a, a.begin() + 4);第二个参数是迭代器,指向旋转后的首个元素。

检查式的算法

rg::min rg::max

rg::any_of rg::all_of rg::none_of

rg::find rg::find_if

其它……

还有很多很多没有提到的 STL 算法,但它们在程序设计中用到的不多。如果感兴趣的话可以自行学习。

其实已排序范围上的算法在算法竞赛中用得比较多。

最近更新:
代码未运行