STL大致分类:
(1)容器
序列式容器:vector(向量容器)、deque(双端队列)、list(双向列表)
关联式容器:集合(set、multiset)、映射(map、multimap)
容器适配器:stack、queue、priority_queue
(2)迭代器
Input iterator、Output iterator、Forward iterator、Bidirectional iterator、Random iterator
(3)泛型算法
(4)仿函数(函数对象)
绑定器:bind1st、bind2nd
取反器:not1、not2
(5)空间配置器
这里先看一下,序列式容器@.@(推眼镜)
(1)、vector向量容器
vector的数据结构:线性连续空间
template<class T,class Alloc = alloc>
class vector
{
...
protected:
iterator start; //表示目前使用空间的头
iterator finish; //表示目前使用空间的尾
iterator end_of_storage; //表示目前可用空间的尾
}
运用这三个迭代器可以轻便的提供首尾标识、首尾元素值、容量、大小、空容器判断、下标运算[ ]
template<class T,class Alloc = alloc>
class vector
{
...
public:
iterator begin() {return start;}
iterator end() {return finish;}
size_type size() const {return size_type(end()-begin());}
size_type capacity() const {return size_type(end_of_storage-begin());}
bool empty const{return begin() == end();}
reference operator[](size_type n){return *(begin()+n);}
reference front(return *begin();)
reference back(return *end()-1;)
}
功能函数:
void push_back( const T& x); //尾插
void pop_back(); //取出尾端的元素
iterator erase(iterator position); //删除position处的元素
void resize( ) {size_type new_size}; //重置容器大小
void insert(iterator position,size_type n,const T& x);
2、list(循环双向链表)
template<class T>
struct _list_node
{
typedef void* void_pointer;
void_pointer prev;
void_pointer next;
T data;
}
list结点的结构
list的重要特性:插入insert操作和接合splice操作都不会导致原来的list迭代器失效,只有“指向被删除元素”的迭代器会失效。
list的数据结构:
template<class T,class Alloc = alloc>
struct list
{
protected:
typedef _list_node<T> list_node;
public:
typedef list_node* link_type;
protected:
link_type node; //只要一个指针,便可表示整个环状双向链表
}
list的设计精巧之处,也可以从这里看出,在链表尾端加上一个空白节点node,便能符合STL对于“前闭后开”区间的要求,成为last迭代器。
这个设计有多方便,从下面几个函数就可看出:
iterator begin() {return (link_type)((*node).next);}
iterator end() {return node;}
bool empty(){return node->next == node;}
size_type size() const
{
size_type result = 0;
distance(begin(),end(),result);
return result;
}
reference front() {return *begin();}
reference back() {return *(--end());}
List示意图
void push_back(const T& x){insert(end( ),x);} //尾插
void push_front (const T& x) {insert(begin(),x)} //头插
iterator erase(iterator position); //删除
void pop_front( ) { erase( begin( ) ); }
void pop_back( ) {iterator tmp = end( ); erase(--tmp;) }
void remove(const T& value); //将所有value元素都移除
void unique( ); //移除连续的相同元素,最终剩一个
void splice(iterator position,list &x); //将x移到position所指位置之前
void reverse( ); //链表逆置
void merge(List<T,Alloc>T & x); //合并两个链表
3、deque(双端队列)
deque是双向开口的连续线性空间,既两端都能进行插入删除操作。
它的结构如下:
deque的空间增长直接申请更大的区域串接在头或者尾,所以deque需要在这些分段的连续空间上维护其整体连续的假象并提供随机存储,这样做导致了它复杂的迭代器架构。
deque设计了一个map(一块连续空间,里面存放指向各个分段空间的地址)结构,用于管理不连续的分段。
typedef value_type* pointer;
typedef pointer* map_pointer;
map_pointer map;
map为一个二级指针,指向一块连续的空间,这块空间里的每一个为元素都是一个指针,指向一块更大的存储空间(deque的存储主体)
结构如下:
正因为deque的特殊结构,所以给迭代器带来了不小的压力,对于++operator或者operator++的操作,涉及到跳级。
typedef T value_type;
T* cur; //指向缓冲区的现行元素
T* first; //指向缓冲区的头
T* last; //指向缓冲区的尾
map_pointer node; //同map一样,二级指针,指向map中的元素
map(中控器)、迭代器、缓冲区之间的关系图如下所示:
专门设有start和finish的迭代器
功能函数:
void push_back(const value_type& x); //尾插
void push_front(const value_type& x); //头插
void pop_back(); //取尾部元素
void pop_front(); //取头部元素
iterator erase(iterator position);