Effective STL 第34条

为什么有些算法需要排序的区间

binary_search算法是二分查找, 这种查找需要查找空间的序列是有序的. 为了二分查找的效率,给binary_serach指定的区间,最好用"随机访问迭代器"指定. 因为binary_search运行过程常常需要直接取中间值. 如果迭代器支持随机访问,那么通过中间下标可以快速的访问.但如果迭代器不支持这种快速的随机访问,那binary_search只能通过迭代器自增加或减少一点点的挪动,那样的效率就会很低.
lower_bound(first, last, val) 从区间中找到不小于val值的 (大于或者等于)
upper_bound(first, last,val) 从区间中找到大于val值的元素
pair range = equal_range(a, a + 9, 4); equal_range从区间找到等于val的起始位置和结束位置.
这四个查找都是基于二分法.所以要求区间是排序的区间.

求集合的算法为什么要求是排好序的区间

4个求集合的算法,分别是求并集set_union, 求交集set_intersection, 求差集set_difference, 求对称差集set_symmetric_differnce.
只有了解这四个算法的实现你才能知道为什么他们需要排序空间。

求并集

最笨的做法,取出集合一的元素,然后遍历集合2一下,如果元素也在集合2上,则放入并集。这样的操作对集合一的元素要来一遍,对集合2的元素也要来一遍。复杂度是2(集合1个数)(集合2个数)。
stl的set_union算法是这样的
对于队列s1,s2, 分别从头开始遍历,走一格判断一下:

  • 如果两个元素相同,取s1的元素,取出元素的队列向前一格。
  • 如果两个元素不同,取小的元素,并向前一格
  • 如果有一个集合已经到达尾端,取出另一个集合的所有剩余元素

求交集

set_intersection

  • 如果两个元素相同,取s1元素,并向前一格
  • 如果两个元素不同,s2一直向前
  • 任何一个集合到达尾端,停止操作

求差集

set_difference
注意这个算法的目的是求出s1上有,s2上没有的集合。

  • 如果两个元素相同,都向前一格
  • 如果s1的元素大于s2, s2一直向前
  • 如果s1的元素小于s2, 取出s1元素
  • 如果s2已经到末端,s1的剩余元素取出。

求对称差集

  • 如果两个元素相同,都向前一格
  • 如果两个元素不同,取小元素,小元素的队列向前一格
  • 如果有集合到达尾端,剩余的全部取出。

merge算法

merge算法和set_union的算法很类似,不过有一点微小的区别。
merge最后得到的元素个数一定是两个集合的总和,是两个集合没有损失的合集,并且合集也保持排序性。
但是set_union相同的一对只会取一个保留。具体的做法需要熟悉set_union的算法

inplace_merge算法

这个算法也要求指定的区间段是排过序的。他的目的是用于这种场景。一个容器有两段,【first middle) 【middle last)这两段本身是排序的,【first, last)不满足排序。inplace_merge的目的是把这两段融合,位置还是这个队列,不过实现了完整的排序。

includes算法

目的是判断s1是否涵盖s2
他使用的算法应该类似set_intersection. 也是要求排序的区间。

unique

unique是去重的,但是要注意的是他只能对付连续的重复。所以对于不连续的重复如果也要去除的话,需要先排序一下。

unique_copy

unique_copy 类似unique。 好处是他对原队列是不会影响的。他只会把不重复的数据copy到另一个容器。

你可能感兴趣的:(Effective STL 第34条)