1.容器
STL提供的容器可以分为三种:
序列式容器(Sequence container):这是一种有序(ordered)集合,其内每个元素均有确凿的位置——取决于插入时机和地点,与元素值无关。如:array、vector、deque、list和forward_list。
关联式容器(Associative container):这是一种已排序(sorted)集合,元素位置取决于其value和给定的某个排序准则,插入次序无关。如:set、multiset、map和multimap。
无序容器(Unordered container):这是一种无序集合(unordered collec-tion),其内每个元素的位置无关紧要,唯一重要的是某特定元素是否位于此集合内。元素值及其插入顺序,都不影响元素的位置,而且元素的位置有可能在容器生命中被改变。如:unordered_set、unordered_multiset、unordered_map和unordered_multimap。
1.1 序列式容器(Sequence container)
序列式容器通常由array或linked list来实现。
所有序列式容器都有这个成员函数push_back() 用于添加成员。
所有容器都提供这个成员函数size() 用于获取元素个数,forward_list 例外。
1.1.1 array
arrary对象是在固定大小的数组内管理元素,不可改变元素个数,只能改变元素数值,必须在建立时就指定其大小。
array提供的是随机访问迭代器。
注意,元素个数是array类型的一部分。因此array<int,5>和array<int,10>是两个不同的类型,你不能对此二者进行赋值或比较。
初始化:
array<int, 4> arr; //value未知
array<int, 4> arr={}; //value = 0
array<int, 5> arr = {1,2,3,4,5}; //OK
array<int,5> arr({1,2,3,4,5}); //ERROR
vector<int> vec({1,2,3,4,5}); //OK
元素访问:
arr[index] //不检查index的范围
arr.at(index) //如果index超出范围会抛 out_of_range 异常
arr.front() //不检查第一个元素是否存在
arr.back() //也不检查最后一个元素是否存在
array提供tuple接口。因此你可以用表达式tuple_size<>::value取得元素个数,用tuple_element<>::type取得某特定元素的类型,用get()取得某特定元素。
1.1.2 vector
vector提供随机访问迭代器。
调用reserve()所给的实参如果小于当前vector的容量,不会引发任何效果。C++11引入一个vector新函数:一个不具强制力的要求,可以缩减容量以符合当前的元素个数。因为不具强制力,所以你不能够期望之后的v.capacity==v.size()会获得true。
v.shrink_to_fit();
元素访问规则和上述array的一样。
当 pop_back() 被调用时,确保容器不为空是程序员的责任。
1.1.3 deque
deque提供随机访问迭代器。
deque的内存重分配优于vector,因为deque不必在内存重新分配时复制所有元素。
deque和vector的接口几乎一样,所以如果你不需要什么特殊性质,两者都可试试。
1.1.4 list
list由双向链表(doubly linked list)实现而成。
list不支持随机访问,所用的迭代器是双向迭代器,而非随机访问迭代器。所有用到随机访问迭代器的算法(所有操作元素顺序的算法)都不能用来处理list。list既不提供subscript(下标)操作符,也不提供at()。
list在任何位置上执行安插或删除动作都非常迅速,只需要常量时间。
1.1.5 forward list
forward list 是受到更多限制的list。它只提供前向迭代器,而不提供双向迭代器,它也不支持反向(reverse)迭代器。
forward list不提供成员函数size()。它没有指向最末元素的锚点(anchor)。因此,也不提供用以处理最末元素的成员函数如back()、push_back()和pop_back()。
1.2 关联式容器(Associative container)
关联式容器通常由二叉树(binary tree)来实现。
关联式容器提供的是双向访问迭代器,所有使用随机访问迭代器的算法都不适用于关联式容器。更易型算法也不适用于关联式容器,比如remove(),要删除容器内元素只能调用容器的成员函数erase()。
关联式容器的主要优点是,它能很快找出一个具有某特定value的元素,因为它具备对数复杂度(logarithmic complexity),而任何循序式容器的复杂度是线性。
所有关联式容器都有一个可供选择的template实参,指明排序准则;默认采用操作符<。
所有关联式容器都提供了insert()成员函数,用来安插新元素。
1.2.1 set/multset
查找操作:
set.count(value); //返回"元素值==value"的元素的个数
set.find(value); //返回"元素值==value"的第一个元素,没有返回end()
set.lower_bound(value); //返回第一个"元素值>=value"的位置
set.upper_bound(value); //返回第一个"元素值>value"的位置
set.equal_range(value); //返回"元素值==value"的区间
赋值操作:
set1 = set2;
set1 = std::move(set2);
set1 = initlist;
set1.swap(set2);
swap(set1, set2);
这些操作函数中,赋值操作的两端容器必须具备相同类型,尽管“比较准则”本身可能不同,但其类型必须相同。如果准则不同,准则本身也会连同容器一并被赋值或交换。
1.2.2 map/multmap
map的查找操作及赋值操作和set的一样。
map提供at()以及下标操作符[]可直接访问元素。
1.3 无序容器(Unordered container)
无序容器通常由哈希表hash table来实现。
无序(unordered)容器的主要优点是,当你打算查找一个带某特定值的元素,其速度甚至可能快过关联式容器。
无序容器提供的迭代器至少是前向迭代器,实际上,标准库提供的是双向迭代器。
无序容器的赋值操作和set的一样。
1.4 容器的成员函数
1.4.1 所有容器都拥有的成员函数
bool container::empty() const
sizte_t container::size() const //除forward_list外
size_type container::max_size() const
bool operator==(const container& c1, const container& c2)
bool operator!=(const container& c1, const container& c2)
container& container::operator=(const container& c)
container& container::operator=(container&& c) //除array外
container& container::operator=(initializer-list) //除array外
void container::swap(container& c)
void container::clear() //除array外
iterator container::erase(const_iterator pos) //除forward_list和array之外
对于vector和deque,erase() 操作可能造成“指向其他元素”的 iterator 和 reference 无效;对于所有其他容器,“指向其他元素”的 iterator 和 reference 永远保持有效。
对于序列式容器(list、vector、deque): erase(iter) 不仅会使指向的迭代器生失效,而且会使后续迭代器也失效,所以不能使用 erase(iter++) 删除元素。但erase()返回的是下一个有效迭代器。
对于关联式容器(set、map、multiset、multimap): erase(iter) 只会使指向的迭代器失效,且返回值是void,所以可以使用 erase(iter++) 删除元素。
1.4.2 序列式容器拥有的成员函数
void container::assign(initializer-list) //除array外
void container::assign(size_type num, const T& value) //除array外
void container::assign(InputIterator beg, InputIterator end) //除array外
reference container::front()
const_reference container::front() const
reference container::back() //除forward_list外
const_reference container::back () const //除forward_list外
1.4.3 关联式容器拥有的成员函数
iterator container::lower_bound(const T& value)
const_iterator container::lower_bound(const T& value) const
iterator container::upper_bound(const T& value)
const_iterator container::upper_bound(const T& value) const
1.4.4 序列式容器和关联式容器拥有的成员函数
bool operator<(const container& c1, const container& c2)
bool operator<=(const container& c1, const container& c2)
bool operator>(const container& c1, const container& c2)
bool operator>=(const container& c1, const container& c2)
1.4.5 关联式容器和无序容器拥有的成员函数
size_type container::count(const T& value) const
iterator container::find(const T& value)
const_iterator container::find(const T& value) const
pair<iterator,iterator> container::equal_range(const T& value)
pair<const_iterator,const_iterator>container::equal_range(const T&value) const
iterator container::insert(const T& value) 允许重复的容器 order/unorder multiset mulitmap
iterator container::insert(T&& value) 允许重复的容器 order/unorder multiset mulitmap
pair<iterator,bool> container::insert(const T& value) 不允许重复的容器 order/unorder set map
pair<iterator,bool> container::insert(T&& value) 不允许重复的容器 order/unorder set map
iterator container::emplace(args) 允许重复的容器 order/unorder multiset mulitmap
pair<iterator,bool> container::emplace(args) 不允许重复的容器 order/unorder set map
size_type container::erase(const T& value) 此函数不会造成指向其他元素的iterator和reference失效。
array vector deque string拥有的成员函数:
reference container::at(size_type idx)
const_reference container::at(size_type idx) const
reference container::operator[](size_type idx)
const_reference container::operator[](size_type idx) const
map和unordered map拥有的成员函数:
T& map::operator at(const key_type& key)
const T& map::operator at(const key_type& key) const
T& map::operator[](const key_type& key)
T& map::operator[](key_type&& key)
2.迭代器(Iterator)
迭代器是smart pointer,具有遍历复杂数据结构的能力,其内部运作机制取决于其所遍历的数据结构。因此,每一种容器都必须提供自己的迭代器。事实上每一种容器的确都将其迭代器以嵌套(nested)方式定义于class内部。因此各种迭代器的接口虽然相同,类型却各自不同。
任何容器都定义有两种迭代器类型:container::iterator 和 container::const_iterator。
迭代器分五种:输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器。前向迭代器继承自输入迭代器;双向迭代器继承自前向迭代器;随机访问迭代器继承自双向迭代器。
随机访问迭代器:array、 vector、 deque、 string
前向迭代器: forward_list、 unorder_container
双向迭代器:list、 associative_container
2.1 辅助函数
C++标准库为迭代器提供了一些辅助函数:advance()、next()、prev()、distance()和iter_swap()。前四者提供给所有迭代器一些“原本只有随机访问迭代器才有”的能力:前进或后退多个元素,及处理迭代器之间的距离。最后一个辅助函数允许你交换两个迭代器的value。
void advance (InputIterator& pos,Dist n)
该函数并不检查迭代器是否超过序列的end(),因为迭代器通常不知道其所操作的容器,因此无从检查。所以,调用advance()有可能导致不明确行为。对双向迭代器或随机访问迭代器n可以是负值,表示向后退。
ForwardIterator next (ForwardIterator pos) //forward迭代器pos前进1个位置
ForwardIterator next (ForwardIterator pos, Dist n) //forward迭代器pos前进n个位置
其中,Dist是类型std::iterator_traits<ForwardIterator>::difference_type。其内部将对一个临时对象调用advance(pos,n)。如果处理的是bidirectional和random-access迭代器,n可为负值,导致后退移动。next()也不检查是否会跨越序列的end(),因此调用者必须自行担保其结果有效。
BidirectionalIterator prev (BidirectionalIterator pos) //bidirectional迭代器pos后退1个位置
BidirectionalIterator prev (BidirectionalIterator pos, Dist n) //bidirectional迭代器pos后退n个位置
其中,Dist是类型std::iterator_traits<BidirectionalIterator>::difference_type。其内部将对一个临时对象调用advance(pos,-n)。prev()并不检查是否会跨越序列的begin(),因此调用者必须自行担保其结果有效。
Distdistance (InputIterator pos1,InputIterator pos2) //返回两个input迭代器pos1和pos2之间的距离。
void iter_swap (ForwardIterator1 pos1,ForwardIterator2 pos2) //交换迭代器pos1和pos2所指的值。
2.2 ++pos VS pos++
前置式比后置式效率更高。因为后者内部需要一个临时对象,因为它必须存放迭代器的原本位置并返回之,所以一般情况下最好使用前置++pos,不要用后置pos++。
2.3 range-base for循环 VS 迭代器
使用range-base时,会被解释为 iterator,而不是const_iterator,这也是为什么我们是在使用range-base时,会加引用&的原因了。
2.4 迭代器之适配器
2.4.1 安插型迭代器
back_inserter(coll); //内部调用push_back()
front_inserter(coll); //内部调用 push_front()
inserter(coll, pos); //在指定位置的前方插入,这是唯一可用于关联容器的安插型迭代器。在关联式容器和无序容器中,你所给的位置只是一个提示,帮助容器确定从什么地方开始查找正确的安插位置。容器有完全的自由决定要不要忽略它。
2.4.2 串流迭代器
Stream iterator被用来读/写stream。它们提供了必要的抽象性,使得来自键盘的输入像是个集合(collection),你能够从中读取内容。同样道理,你也可以把一个算法的输出结果重新导向到某个文件或屏幕上。
2.4.3 反向迭代器
所有提供双向(bidirectional)或随机访问(random-access)迭代器的容器(也就是forward_list之外的所有序列式容器和所有关联式容器)都可以通过它们的成员函数rbegin()和rend()产生一个反向迭代器。
forward_list 和所有无序容器都没有提供回向迭代(backward-iteration)接口,即rbegin()、rend()等等。原因是那些容器内部实现只是使用singly linked list串起所有元素。
2.4.4 搬移迭代器
这种迭代器始自C++11,用来将任何“对低层元素(underlying element)的访问”转换为一个move操作。也就是说,它们允许从一个容器移动元素至另一个容器,不论是在构造函数内或是在运用算法时。
2.5 迭代器特性
C++标准库提供了一种特殊的template结构来定义所谓的迭代器特性(iterator trait),该结构包含迭代器相关的所有信息,为“迭代器应具备的所有类型定义(包括迭代器种类、元素类型等)”提供一致的接口:
namespace std{
template <typename T>
struct iterator_traits{
typedef typename T::iterator_category iterator_category;
typedef typename T::value_type value_type;
typedef typename T::diffrence_type diffrence_type;
typedef typename T::pointer pointer;
typedef typename T::reference reference;
};
}
2.6 自定义迭代器
1.提供必要的五种类型定义。
C++标准库提供了一个特殊的基类(base class) iterator<>,专门用来进行这一定义:
class MyIterator : public std::iterator<bidirectional_iterator_tag, type, std::ptrdiff_t, *type, &type>{
. . .;
};
其中,第一个template参数用来定义迭代器种类,第二个参数用来定义元素类型,第三参数用来定义difference(距离)类型,第四个参数用来定义pointer类型,第五个参数用来定义reference类型。末尾的三个参数有默认值ptrdiff_t、type*和type&,可以省略。
2.为 iterator_traits结构提供一个(偏)特化版本。
3.算法
STL提供了一些标准算法,包括查找、排序、拷贝、重新排序、修改、数值运算等基本而普遍的算法。算法并非容器类的成员函数,而是一种搭配迭代器使用的全局函数。
pos min_element(begin, end);
pos max_element(begin, end);
sort(begin, end); //这里不能使用const_iterator,因为sort会改变元素的值
pos find(begin, end, value); //这里也不能使用const_iterator
reverse(begin, end); //这里也不能使用const_iterator
3.1 非更易型算法(Notmodifying Algorithm)
非更易型算法不会改动元素值,也不会改变元素次序。
3.1.1 元素计数
difference_type count(InputIterator beg, InputIterator end, const T&value)
difference_type count_if(InputIterator beg, InputIterator end, UnaryPredicate op)
3.1.2 最大值和最小值
ForwardIterator min_element(ForwardIterator beg, ForwardIterator end)
ForwardIterator min_element(ForwardIterator beg, ForwardIterator end, CompFunc op)
ForwardIterator max_element(ForwardIterator beg, ForwardIterator end)
ForwardIterator max_element(ForwardIterator beg, ForwardIterator end, CompFunc op)
pair<ForwardIterator,ForwardIterator> minmax_element(ForwardIterator beg, ForwardIterator end)
pair<ForwardIterator,ForwardIterator> minmax_element(ForwardIterator beg, ForwardIterator end, CompFunc op)
注意:如果存在多个最小值或最大值,min_element() 和 max_element() 返回其所找到的第一个目标元素;minmax_element() 返回第一个最小元素和最后一个最大元素。所以,max_element() 和minmax_element() 返回的最大元素不是同一个。
3.1.3 查找元素
查找第一个匹配的值:
InputIterator find(InputIterator beg, InputIterator end, const T&value)
InputIterator find_if(InputIterator beg, InputIterator end, UnaryPredicate op)
InputIterator find_if_not(InputIterator beg, InputIterator end, UnaryPredicate op)
如果是已排序区间,使用lower_bound()、upper_bound()、equal_range() 或 binary_search() 算法以获得更高效能。
associative 和 unordered 容器提供有等效的成员函数 find() ,拥有较好复杂度。
查找前n个连续匹配值:
ForwardIterator search_n(ForwardIterator beg, ForwardIterator end, Size count, const T&value)
ForwardIterator search_n(ForwardIterator beg, ForwardIterator end, Size count, const T&value, BinaryPredicate op)
找到了第一元素位置,如果没有找到匹配元素,两种形式都返回end。
查找第一个子区间:
ForwardIterator1 search(ForwardIterator1 beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd)
ForwardIterator1 search(ForwardIterator1 beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd, BinaryPredicate op)
返回 [beg,end) 区间内“与 [searchBeg,searchEnd) 区间完全吻合”的第一个子区间内的第一元素位置,如果没有找到匹配元素,则返回end。
查找最后一个子区间:
ForwardIterator1 find_end(ForwardIterator1 beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd)
ForwardIterator1 find_end(ForwardIterator1 beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd, BinaryPredicate op)
查找某些元素的第一次出现地点:
InputIterator find_first_of(InputIterator beg, InputIterator end, ForwardIterator searchBeg, ForwardIterator searchEnd)
InputIterator find_first_of(InputIterator beg, InputIterator end, ForwardIterator searchBeg, ForwardIterator searchEnd, BinaryPredicate op)
返回第一个既出现于[beg,end) 区间也出现于[searchBeg,searchEnd)区间的元素的位置。
查找两个连续且相等的元素:
ForwardIterator adjacent_find(ForwardIterator beg, ForwardIterator end)
ForwardIterator adjacent_find(ForwardIterator beg, ForwardIterator end, BinaryPredicate op)
3.1.4 区间比较
检验相等性:
bool equal(InputIterator1 beg, InputIterator1 end, InputIterator2 cmpBeg)
bool equal(InputIterator1 beg, InputIterator1 end, InputIterator2cmpBeg, BinaryPredicate op)
判断 [beg,end) 区间内的元素是否都和“以cmpBeg开头的区间”内的元素相等。
请确保“以cmpBeg开头”的区间内含足够元素。
当序列不相等时,如果想要了解其间的不同,可使用 mismatch() 算法。
测试不定序之相等性:
bool is_permutation(ForwardIterator1 beg1, ForwardIterator1 end1, ForwardIterator2 beg2)
bool is_permutation(ForwardIterator1 beg1, ForwardIterator1 end1, ForwardIterator2 beg2, CompFunc op)
检测 [beg1,end1) 区间内的元素是否为 beg2 起始之区间元素的一个排列组合,即两个序列内含的元素数值相同但次序不同。
查找第一处不同:
pair<InputIterator1,InputIterator2> mismatch(InputIterator1 beg, InputIterator1 end, InputIterator2 cmpBeg)
pair<InputIterator1,InputIterator2> mismatch(InputIterator1 beg, InputIterator1 end, InputIterator2 cmpBeg, BinaryPredicate op)
返回 [beg,end)区间和“以cmpBeg起始的区间”内第一组两两相异的对应元素。
请确保“以cmpBeg开头”的区间内含足够元素。
检验“小于”:
bool lexicographical_compare(InputIterator1 beg1, InputIterator1 end1, InputIterator2 beg2, InputIterator2 end2)
bool lexicographical_compare(InputIterator1 beg1, InputIterator1 end1, InputIterator2 beg2, InputIterator2 end2, CompFunc op)
判断[beg1,end1)区间内的元素是否小于[beg2,end2)的元素。
3.1.5 Predicate用以检验区间
检验是否排序:
bool is_sorted(ForwardIterator beg, ForwardIterator end)
bool is_sorted(ForwardIterator beg, ForwardIterator end, BinaryPredicate op)
ForwardIterator is_sorted_until(ForwardIterator beg, ForwardIterator end)
ForwardIterator is_sorted_until(ForwardIterator beg, ForwardIterator end, BinaryPredicate op) // 返回[beg,end)区间内第一个破坏排序的元素。如果没有这样的元素,返回end
检验是否被分割:
bool is_partitioned(InputIterator beg, InputIterator end, UnaryPredicate op) //判断 [beg,end) 区间内的元素是否被分割,也就是所有符合op()的元素都被置于所有不符合的元素之前
ForwardIterator partition_point(ForwardIterator beg, ForwardIterator end, BinaryPredicate op) //返回 [beg,end) 区间中的第一个元素的位置。因此,对于[beg,end),is_partitioned() 必定产出true
检验是否形成Heap(最大值元素在第一位):
bool is_heap(RandomAccessIterator beg, RandomAccessIterator end)
bool is_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op)
RandomAccessIterator is_heap_until(RandomAccessIterator beg, RandomAccessIterator end)
RandomAccessIterator is_heap_until(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op) //返回[beg,end) 区间内第一个“破坏排序使无法成为heap”的元素位置(该元素将会比第一元素更大);如果没有这样的元素就返回end。
检验All、Any或None:
bool all_of(InputIterator beg, InputIterator end, UnaryPredicate op)
bool any_of(InputIterator beg, InputIterator end, UnaryPredicate op)
bool none_of(InputIterator beg, InputIterator end, UnaryPredicate op)
3.2 更易型算法(Manipulating Algorithm)
更易型算法是指会移除或重排或修改元素的算法。
更易型算法不得用于关联式容器和无序容器,因为它们的元素被视为常量。
3.2.1 复制元素
OutputIterator copy(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg)
OutputIterator copy_if(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, UnaryPredicate op)
OutputIterator copy_n(InputIterator sourceBeg, Size num, OutputIterator destBeg)
BidirectionalIterator2 copy_backward(BidirectionalIterator1 sourceBeg, BidirectionalIterator1 sourceEnd, BidirectionalIterator2 destEnd)
copy正向遍历,而copy_backward是反向遍历的。上述四个算法源和目的区间都不能重叠。
自C++11起,如果源端元素不再被使用,你应该以move()取代copy(),以move_backward()取代copy_backward()。
如果希望在复制过程中反转元素次序,应使用reverse_copy();如果希望在复制的同时移除元素,应使用算法 remove_copy() 和 remove_copy_if();如果希望在复制过程中改动元素,请使用 transform() 或 replace_copy() 。
如果想把容器内的所有元素赋值给另一个容器,应当使用赋值操作符(当两个容器的类型相同时)或使用容器的 assign() 成员函数(当两个容器的类型不同时)。
3.2.2 搬移元素
OutputIterator move(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg)
BidirectionalIterator2 move_backward(BidirectionalIterator1 sourceBeg, BidirectionalIterator1 sourceEnd, BidirectionalIterator2 destEnd)
和copy算法一样,两个move算法的源和目的区间不能重叠。
3.2.3 转换和结合元素
OutputIterator transform(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, UnaryFunc op) //返回目标区间内“最后一个被转换元素”的下一位置
请确保目标区间有足够空间,否则请使用insert iterator。
sourceBeg与destBeg可以完全相同。
OutputIterator transform(InputIterator1 source1Beg, InputIterator1 source1End, InputIterator2 source2Beg, OutputIterator destBeg, BinaryFunc op)
请确保第二源区间有足够空间(至少拥有和第一源区间相同的大小);同时也需要确保目标区间有足够空间,否则请使用insert iterator。
source1Beg、source2Beg和destBeg可相同。
3.2.4 互换元素
ForwardIterator2 swap_ranges(ForwardIterator1 beg1, ForwardIterator1 end1, ForwardIterator2 beg2)
返回第二区间中“最后一个被交换元素”的下一位置。
请确保目标区间有足够空间,且两区间不得重叠。
如果要将相同类型的两个容器内的所有元素都互换,应使用 swap() 成员函数。
3.2.5 赋值
void fill(ForwardIterator beg, ForwardIterator end, const T&newValue)
void fill_n(OutputIterator beg, Size num, const T&newValue)
void generate(ForwardIterator beg, ForwardIterator end, Func op)
void generate_n(OutputIterator beg, Size num, Func op)
请确保目标区间有足够空间,要不就得使用insert iterator。
自C++11起,xxx_n() 返回最后被改动的元素的下一位置(beg+num),如果num是负值则返回beg。
赋予一系列递增值:
void iota(ForwardIterator beg, ForwardIterator end, T startValue)
3.2.6 替换元素
替换序列内的元素:
void replace(ForwardIterator beg, ForwardIterator end, const T&oldValue, const T&newValue)
void replace_if(ForwardIterator beg, ForwardIterator end, UnaryPredicate op, const T&newValue)
复制并替换元素:
OutputIterator replace_copy(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, const T&oldValue, const T&newValue)
OutputIterator replace_copy_if(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, UnaryPredicate op, const T&newValue)
请确保目标区间有足够空间,要不就得使用insert iterator。
3.3 移除型算法
移除型算法并不会改变元素的数量,它们只是以逻辑上的思考,将原本置于后面的“不移除元素”向前移动,覆盖那些应被移除的元素,并返回新区间的逻辑终点(也就是最后一个“不移除元素”的下一位置)。
3.3.1 移除某些元素
ForwardIterator remove(ForwardIterator beg, ForwardIterator end, const T&value)
ForwardIterator remove_if(ForwardIterator beg, ForwardIterator end, UnaryPredicate op)
由于元素会被改动,所以这些算法不可用于associative或unordered容器,它们提供了功能类似的成员函数erase()。
List提供了一个效果相同的成员函数remove(),效能较高,原因是它不重新赋值,而是重新链接pointer。
OutputIterator remove_copy(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, const T&value)
OutputIterator remove_copy_if(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, UnaryPredicate op)
请确保目标区间有足够空间,要不就得使用insert iterator。两个算法都返回目标区间中最后一个被复制元素的下一位置(也就是第一个未被覆盖的元素)。
3.3.2 移除重复元素
移除连续重复元素:
ForwardIterator unique(ForwardIterator beg, ForwardIterator end)
ForwardIterator unique(ForwardIterator beg, ForwardIterator end, BinaryPredicate op)
以上两种形式都会移除连续重复元素中的多余元素。因此源序列必须先经过排序,才能使用这个算法移除所有重复元素。在调用这些算法之后,从此使用返回的新逻辑终点,不再使用原始终点end。
List提供了一个效果相同的成员函数unique(),原因是它不重新赋值,而是重新链接pointer。
复制过程中移除重复元素:
OutputIterator unique_copy(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg)
OutputIterator unique_copy(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, BinaryPredicate op)
两种形式都是 copy() 和 unique() 的组合。请确保目标区间有足够空间,否则使用insert iterator。
3.4 变序型算法
变序型算法会改变元素的次序,但不改变元素值。这些算法不能用于 associative 和unordered容器,因为那些容器内的元素有一定次序,不能随意变动之。
3.4.1 反转元素次序
void reverse(BidirectionalIterator beg, BidirectionalIterator end)
OutputIterator reverse_copy(BidirectionalIterator sourceBeg, BidirectionalIterator sourceEnd, OutputIterator destBeg)
3.4.2 旋转元素
ForwardIterator rotate(ForwardIterator beg, ForwardIterator newBeg, ForwardIterator end)
将 [beg,end) 区间内的元素旋转,执行后 *newBeg 成为新的第一元素。
请确保newBeg是 [beg,end) 区间内的一个有效位置,否则会引发不确定的行为。
OutputIterator rotate_copy(ForwardIterator sourceBeg, ForwardIterator newBeg, ForwardIterator sourceEnd, OutputIterator destBeg)
3.4.3 排列元素
bool next_permutation(BidirectionalIterator beg, BidirectionalIterator end)
bool next_permutation(BidirectionalIterator beg, BidirectionalIterator end, BinaryPredicate op)
bool prev_permutation(BidirectionalIterator beg, BidirectionalIterator end)
bool prev_permutation(BidirectionalIterator beg, BidirectionalIterator end, BinaryPredicate op)
3.4.4 对元素重新洗牌
void shuffle(RandomAccessIterator beg, RandomAccessIterator end, UniformRandomNumberGenerator&& eng)
void random_shuffle(RandomAccessIterator beg, RandomAccessIterator end)
void random_shuffle(RandomAccessIterator beg, RandomAccessIterator end, RandomFunc&& op)
3.4.5 将元素向前搬
ForwardIterator partition(ForwardIterator beg, ForwardIterator end, UnaryPredicate op)
BidirectionalIterator stable_partition(BidirectionalIterator beg, BidirectionalIterator end, UnaryPredicate op)
3.4.6 划分为两个子区间
pair<OutputIterator1,OutputIterator2> partition_copy(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator1 destTrueBeg, OutputIterator2 destFalseBeg, UnaryPredicate op)
3.5 排序算法
由于(forward) list和associative及unordered容器不提供random-access iterator,所以你不能使用这些容器作为排序算法的目标区。
3.5.1 对所有元素排序
void sort(RandomAccessIterator beg, RandomAccessIterator end)
void sort(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op)
void stable_sort(RandomAccessIterator beg, RandomAccessIterator end)
void stable_sort(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op)
sort()和stable_sort() 的区别:stable_sort()保证相等之各元素的相对次序在排序后保持不变。
3.5.2 局部排序
void partial_sort(RandomAccessIterator beg, RandomAccessIterator sortEnd, RandomAccessIterator end)
void partial_sort(RandomAccessIterator beg, RandomAccessIterator sortEnd, RandomAccessIterator end, BinaryPredicate op)
RandomAccessIterator partial_sort_copy(InputIterator sourceBeg, InputIterator sourceEnd, RandomAccessIterator destBeg, RandomAccessIterator destEnd)
RandomAccessIterator partial_sort_copy(InputIterator sourceBeg, InputIterator sourceEnd, RandomAccessIterator destBeg, RandomAccessIterator destEnd, BinaryPredicate op)
partial_sort_copy()将元素从源区间 [sourceBeg,sourceEnd) 复制到目标区间 [destBeg,destEnd)并且进行排序。“被排序(被复制)的元素量”是源区间和目标区间两者所含元素量的较小值。
3.5.3 根据第n个元素排序
void nth_element(RandomAccessIterator beg, RandomAccessIterator nth, RandomAccessIterator end)
void nth_element(RandomAccessIterator beg, RandomAccessIterator nth, RandomAccessIterator end, BinaryPredicate op)
3.5.4 heap算法
就排序而言, heap是一种特别的元素组织方式,应用于heap排序法(heapsort)。Heap可被视为一个以序列式集合(sequential collection)实现而成的二叉树,具有两大性质:
1.第一个元素总是最大。
2.总是能够在对数时间(logarithmic time)内增加或移除一个元素。
Heap是实现priority queue(其内元素会自动排序)的一个理想结构,因此heap算法也被prior ity_queue容器使用。
void make_heap(RandomAccessIterator beg, RandomAccessIterator end)
void make_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op)
void push_heap(RandomAccessIterator beg, RandomAccessIterator end)
void push_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op)
void pop_heap(RandomAccessIterator beg, RandomAccessIterator end)
void pop_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op)
void sort_heap(RandomAccessIterator beg, RandomAccessIterator end)
void sort_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op)
注意:sort_heap() 算法一旦结束,该区间就不再是个heap了。
3.6 已排序区间算法
关于此处所给的算法,associative和unordered容器提供了对应的成员函数。
3.6.1 查找元素
bool binary_search(ForwardIterator beg, ForwardIterator end, const T&value)
bool binary_search(ForwardIterator beg, ForwardIterator end, const T&value, BinaryPredicate op)
bool includes(InputIterator1 beg, InputIterator1 end, InputIterator2 searchBeg, InputIterator2 searchEnd)
bool includes(InputIterator1 beg, InputIterator1 end, InputIterator2 searchBeg, InputIterator2 searchEnd, BinaryPredicate op)
查找第一个或最后一个可能位置:
ForwardIterator lower_bound(ForwardIterator beg, ForwardIterator end, const T&value)
ForwardIterator lower_bound(ForwardIterator beg, ForwardIterator end, const T&value, BinaryPredicate op)
ForwardIterator upper_bound(ForwardIterator beg, ForwardIterator end, const T&value)
ForwardIterator upper_bound(ForwardIterator beg, ForwardIterator end, const T&value, BinaryPredicate op)
lower_bound() 返回第一个“大于等于 value”的元素位置。
upper_bound() 返回第一个“大于value”的元素位置。
如果不存在“其值为value”的元素,上述所有算法都返回end。
pair<ForwardIterator,ForwardIterator> equal_range(ForwardIterator beg, ForwardIterator end, const T&value)
pair<ForwardIterator,ForwardIterator> equal_range(ForwardIterator beg, ForwardIterator end, const T&value, BinaryPredicate op)
3.6.2 合并元素
两个集合的总和:
OutputIterator merge(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg)
OutputIterator merge(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op)
执行结束后,目标区间内的所有元素都将处于排序状态下。
源区间和目标区间两者不可重叠。请确保目标区间有足够空间,否则请使用insert iterator。
两个集合的并集:
OutputIterator set_union(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg)
OutputIterator set_union(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op)
源区间和目标区间两者不可重叠。请确保目标区间有足够空间,否则请使用insert iterator。
两个集合的交集:
OutputIterator set_intersection(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg)
OutputIterator set_intersection(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op)
源区间和目标区间两者不可重叠。请确保目标区间有足够空间,否则请使用insert iterator。
如果某个源区间内原就存在有重复元素,则目标区间内也会有重复元素——重复的次数是两个源区间内的重复次数的较小值。
两个集合的差集:
OutputIterator set_difference(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg)
OutputIterator set_difference(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op)
源区间和目标区间两者不可重叠。请确保目标区间有足够空间,否则请使用insert iterator。
如果某个源区间内原就存在有重复元素,则目标区间内也会有重复元素——重复的次数是第一源区间内的重复次数减去第二源区间内的相应重复次数,如果第二源区间内的重复次数大于第一源区间内的相应重复次数,目标区间内的对应重复次数将会是0。
OutputIterator set_symmetric_difference(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg)
OutputIterator set_symmetric_difference(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op)
合并连贯之已排序区间:
void inplace_merge(BidirectionalIterator beg1, BidirectionalIterator end1, BidirectionalIterator beg2, BidirectionalIterator end2)
void inplace_merge (BidirectionalIterator beg1, BidirectionalIterator end1, BidirectionalIterator beg2, BidirectionalIterator end2, BinaryPredicate op)
3.7 数值算法
运用数值算法之前,必须先包含头文件 <numeric>。
3.7.1 运算后产生结果
对数列进行某种运算:
T accumulate(InputIterator beg, InputIterator end, T initValue)
T accumulate(InputIterator beg, InputIterator end, T initValue, BinaryFunc op)
计算两数列的内积:
T inner_product(InputIterator1 beg1, InputIterator1 end1, InputIterator2 beg2, T initValue)
T inner_product (InputIterator1 beg1, InputIterator1 end1, InputIterator2beg2, T initValue, BinaryFunc op1, BinaryFunc op2)
3.7.2 相对数列和绝对数列之间的转换
将相对值转换成绝对值:
OutputIterator partial_sum(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg)
OutputIterator partial_sum(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, BinaryFunc op)
将绝对值转换成相对值:
OutputIterator adjacent_difference(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg)
OutputIterator adjacent_difference(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, BinaryFunc op)