《STL Tutorial Reference》Chapt 5 STL overview
5.1 STL组成
- 容器
- 迭代器
- 算法
STL的概念是基于数据和操作的分离。
数据由容器类管理,操作是由可配置的算法定义,迭代器则是两者的黏合剂
STL的概念和OOP思想是相矛盾的。这样做的原因:理论上,你可以将每种容器和每种算法结合,结果很灵活但仍是非常小的framework.
STL是很好的Generic Programming的例子。
5.2 容器
可以将容器大致划分为2类:
1)序列容器 ordered collections. 3个预定义的序列容器: vector, deque, list
2)关联容器 sorted collections. 4个预定义的关联容器:set, map, multiset, multimap
你可以将关联容器看作特殊的序列容器,因为sorted collections是依据sorting criterion而有序的。关联容器的自动排序并不意味着它们是专为排序设计的,同样,你也可以为序列容器排序。自动排序的优势在于当你搜索元素时有更好的表现。实际上,你总是可以使用二分搜索。
vector:
使用动态数组管理元素,提供随机访问。可以直接通过下标访问,append或remove末尾元素是非常快,但是插入元素到开始或中间很费时。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> coll; //vector container for integer elements
// append elements with values 1 to 6
for (int i=1; i<=6; ++i) {
coll.push_back(i);
}
//print all elements followed by a space
for (int i=0; i<coll.size( ); ++i) {
cout << coll[i] << ' ';
}
cout << endl;
}
#include <vector>
using namespace std;
int main()
{
vector<int> coll; //vector container for integer elements
// append elements with values 1 to 6
for (int i=1; i<=6; ++i) {
coll.push_back(i);
}
//print all elements followed by a space
for (int i=0; i<coll.size( ); ++i) {
cout << coll[i] << ' ';
}
cout << endl;
}
deque:
动态数组实现,可以在两端增长。插入在开头和末尾是非常快。
// stl/deque1.cpp
#include <iostream>
#include <deque>
using namespace std;
int main()
{
deque<float> coll; //deque container for floating-point elements
//insert elements from 1.1 to 6.6 each at the front
for (int i=1; i<=6; ++i) {
coll.push_front(i*1. 1); //insert at the front
}
//print all elements followed by a space
for (int i=0; i<coll.size(); ++i) {
cout << coll[i] << ' ';
}
cout << endl;
}
#include <iostream>
#include <deque>
using namespace std;
int main()
{
deque<float> coll; //deque container for floating-point elements
//insert elements from 1.1 to 6.6 each at the front
for (int i=1; i<=6; ++i) {
coll.push_front(i*1. 1); //insert at the front
}
//print all elements followed by a space
for (int i=0; i<coll.size(); ++i) {
cout << coll[i] << ' ';
}
cout << endl;
}
list:
实现为一个双端链表。不提供随机访问。插入和移除中间元素非常快。
// stl/list1.cpp
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<char> coll; //list container for character elements
// append elements from 'a' to 'z'
for (char c='a'; c<= ' z '; ++c) {
coll.push_back(c);
}
/* print all elements
* - while there are elements
* - print and remove the first element
*/
while (! coll.empty()) {
cout << coll.front() << ' ';
coll.pop_front();
}
cout << endl;
}
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<char> coll; //list container for character elements
// append elements from 'a' to 'z'
for (char c='a'; c<= ' z '; ++c) {
coll.push_back(c);
}
/* print all elements
* - while there are elements
* - print and remove the first element
*/
while (! coll.empty()) {
cout << coll.front() << ' ';
coll.pop_front();
}
cout << endl;
}
string:
basic_string<>, string, wstring
关联容器会依据某种顺序准则自动排序,默认使用运算符<
关联容器典型的实现为二叉树。这样每个元素有1个parent、2个child。左子树有更小的值,右子树有更大的值。关联容器区分在它们支持的元素的种类以及它们怎样处理重复
set, map, multiset, multimap
#include <iostream>
#include <set>
int main()
{
//type of the collection
typedef std::set<int> IntSet;
IntSet coll; //set container for int values
/* insert elements from 1 to 6 in arbitray order
*- value 1 gets inserted twice
*/
coll.insert(3);
coll.insert(1);
coll.insert(5);
coll.insert(4);
coll.insert(1);
coll.insert(6);
coll.insert(2);
/* print all elements
*- iterate over all elements
*/
IntSet::const_iterator pos;
for (pos = coll.begin(); pos != coll.end(); ++pos) {
std::cout << *pos << ' ';
}
std::cout << std::endl;
}
#include <set>
int main()
{
//type of the collection
typedef std::set<int> IntSet;
IntSet coll; //set container for int values
/* insert elements from 1 to 6 in arbitray order
*- value 1 gets inserted twice
*/
coll.insert(3);
coll.insert(1);
coll.insert(5);
coll.insert(4);
coll.insert(1);
coll.insert(6);
coll.insert(2);
/* print all elements
*- iterate over all elements
*/
IntSet::const_iterator pos;
for (pos = coll.begin(); pos != coll.end(); ++pos) {
std::cout << *pos << ' ';
}
std::cout << std::endl;
}
![](/images/cnblogs_com/chio/stl_set.jpg)
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
//type of the collection
typedef multimap<int, string> IntStringMMap;
IntStringMMap coll; //set container for int/string values
//insert some elements in arbitrary order
//- a value with key 1 gets inserted twice
coll.insert(make_pair(5,"tagged"));
coll.insert(make_pair(2,"a"));
coll.insert(make_pair(1,"this"));
coll.insert(make_pair(4,"of"));
coll.insert(make_pair(6,"strings"));
coll.insert(make_pair(1,"is"));
coll.insert(make_pair(3,"multimap"));
/* print all element values
*- iterate over all elements
*- element member second is the value
*/
IntStringMMap::iterator pos;
for (pos = coll.begin(); pos != coll.end(); ++pos) {
cout << pos->second << ' ';
}
cout << endl;
}
#include <map>
#include <string>
using namespace std;
int main()
{
//type of the collection
typedef multimap<int, string> IntStringMMap;
IntStringMMap coll; //set container for int/string values
//insert some elements in arbitrary order
//- a value with key 1 gets inserted twice
coll.insert(make_pair(5,"tagged"));
coll.insert(make_pair(2,"a"));
coll.insert(make_pair(1,"this"));
coll.insert(make_pair(4,"of"));
coll.insert(make_pair(6,"strings"));
coll.insert(make_pair(1,"is"));
coll.insert(make_pair(3,"multimap"));
/* print all element values
*- iterate over all elements
*- element member second is the value
*/
IntStringMMap::iterator pos;
for (pos = coll.begin(); pos != coll.end(); ++pos) {
cout << pos->second << ' ';
}
cout << endl;
}
容器适配器:
预定义的3种容器适配器: stack, queue, priority queue
迭代器:
iterator
每个容器提供了相同的基本函数来使用迭代器访问它们的元素:
begin() - 返回指示首元素的iterator或const_iterator
end() - 返回指示尾元素的iterator或const_iterator
看STL实现源码:
iterator
begin() { return iterator (this->_M_impl._M_start); }
const_iterator
begin() const { return const_iterator (this->_M_impl._M_start); }
iterator
end() { return iterator (this->_M_impl._M_finish); }
const_iterator
end() const { return const_iterator (this->_M_impl._M_finish); }
begin() { return iterator (this->_M_impl._M_start); }
const_iterator
begin() const { return const_iterator (this->_M_impl._M_start); }
iterator
end() { return iterator (this->_M_impl._M_finish); }
const_iterator
end() const { return const_iterator (this->_M_impl._M_finish); }
每个容器定义了2种迭代器类型:
1. container::iterator
is provided to iterate over elements in read/write mode.
2. container: : const_iterator
is provided to iterate over elements in read-only mode.
另外,对于iterator的自增、自减推荐采用前置形式,后置形式因为会生成临时对象的原因,会比前置形式慢
iterator分类:
依据容器内部的数据结构,预定义容器的迭代器属于下列类型之一:
1)bidirectional iterator
使用自增或自减提供向前和向后,不支持“迭代器算术”。list/set/map/multiset/multimap
2) random access iterator
具备1)的全部属性,而且可以提供随机访问,支持“迭代器算术”。
for (pos = coll.begin(); pos != coll.end(); ++pos)
{
//...
}
for (pos = coll.begin() ; pos < coll.end(); ++pos)
{
//...
}
第一种都支持,但是第二种只有随机访问iterator支持
5.4 算法
STL提供标准算法,这些算法提供基本的服务:排序,搜索,拷贝,重排序,修改和数字处理
算法不是容器类的成员函数,而是全局函数,以iterator操作。
例:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> coll;
vector<int>::iterator pos;
//insert elements from 1 to 6 in arbitrary order
coll.push_back(2);
coll.push_back(5);
coll.push_back(4);
coll.push_back(1);
coll.push_back(6);
coll.push_back(3);
//find and print minimum and maximum elements
pos = min_element (coll.begin(), coll.end());
cout << "min: " << *pos << endl;
pos = max_element (coll.begin(), coll.end());
cout << "max: " << *pos << endl;
//sort all elements
sort (coll.begin(), coll.end());
//find the first element with value 3
pos = find (coll.begin(), coll.end(), //range
3); //value
//reverse the order of the found element with value 3 and all following elements
reverse (pos, coll.end());
//print all elements
for (pos=coll.begin(); pos!=coll.end(); ++pos) {
cout << *pos << ' ' ;
}
cout << endl;
}
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> coll;
vector<int>::iterator pos;
//insert elements from 1 to 6 in arbitrary order
coll.push_back(2);
coll.push_back(5);
coll.push_back(4);
coll.push_back(1);
coll.push_back(6);
coll.push_back(3);
//find and print minimum and maximum elements
pos = min_element (coll.begin(), coll.end());
cout << "min: " << *pos << endl;
pos = max_element (coll.begin(), coll.end());
cout << "max: " << *pos << endl;
//sort all elements
sort (coll.begin(), coll.end());
//find the first element with value 3
pos = find (coll.begin(), coll.end(), //range
3); //value
//reverse the order of the found element with value 3 and all following elements
reverse (pos, coll.end());
//print all elements
for (pos=coll.begin(); pos!=coll.end(); ++pos) {
cout << *pos << ' ' ;
}
cout << endl;
}
5.4.1 范围
所有的算法处理一个或多个范围。范围的有效性依赖于用户:包括范围边界是否可到达、两个iterator是否属于同一个容器、begin iterator处在了end iterator后
所有的算法使用半开范围,即[begin, end)