泛型程序设计(generic programming)的思想 : 模板机制,以及标准模板库STL 。
标准模板库 (STL,Standard Template Libaray)
一些常用数据结构和算法的模板的集合。将一些常用的数据结构(比如链表,数组,二叉树)和算法(比如排序,查找)写成模板,以后则不论数据结构里放的是什么对象,算法针对什么样的对象,则都不必重新实现数据结构,重新编写算法。
可以用于存放各种类型的数据(基本类型的变量,对象等)的数据结构,都是类模版,分为三种:
vector,deque,list
set,multiset,map,multimap
stack,queue,priority_queue
对象被插入容器中时,被插入的是对象的一个复制品。许多算法,比如排序,查找,要求对容器中的元素进行比较,有的容器本身就是排序的,所以,放入容器的对象所属的类,往往还应该重载 ==
和 <
运算符。
容器并非排序的,元素的插入位置同元素的值无关。有 vector,deque,list
三种。
vector 头文件
动态数组。元素在内存连续存放。随机存取任何元素都能在常数时间完成。在尾端增删元素具有较佳的性能(大部分情况下是常数时间)。
— | A0 | A1 | A2 | — | — | — | — | — | — | — | An | — |
---|---|---|---|---|---|---|---|---|---|---|---|---|
begin | end |
deque 头文件
双向队列。元素在内存连续存放。随机存取任何元素都能在常数时间完成(但次于vector)。在两端增删元素具有较佳的性能(大部分情况下是常数时间)。
— | — | A0 | A1 | A2 | A3 | A4 | A5 | — | — | — | — | — | — | — |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
begin | end |
list 头文件
双向链表。元素在内存不连续存放。在任何位置增删元素都能在常数时间完成。不支持随机存取。
set/multiset 头文件
set 即集合。set中不允许相同元素,multiset中允许存在相同的元素。
map/multimap 头文件
map与set的不同在于map中存放的元素有且仅有两个成员变量,一个名为first,另一个名为second,map根据first值对元素进行从小到大排序,并可快速地根据first来检索元素。那first
则相当于关键字,second
则存储的是值;
map同multimap的不同在于是否允许相同first值的元素,即关键字可重复与否;
stack:头文件
栈。是项的有限序列,并满足序列中被删除、检索和修改的项只能是最近插入序列的项(栈顶的项)。后进先出
。
queue头文件
队列。插入只可以在尾部进行,删除、检索和修改只允许从头部进行。先进先出
。
priority_queue 头文件
优先级队列。最高优先级元素总是第一个出列
定义一个容器类的迭代器的方法可以是:
容器类名::iterator 变量名;
容器类名::const_iterator 变量名;
容器类名::reverse_iterator 变量名;
容器类名::const_reverse_iterator 变量名;
访问一个迭代器指向的元素:*选代器变量名。
迭代器上可以执行++操作,以使其指向容器中的下一个元素。如果迭代器到达了容器中的最后一个元素的后面,此时再使用它,就会出错,类似于使用NULL或未初始化的指针一样。
有的算法,例如sort,binary_search需要通过随机访问迭代器来访问容器中的元素,那么list以及关联容器就不支持该算法!
成员函数:
成员函数 | 作用 |
---|---|
vector(); | 无参构造函数,将容器初始化成空的 |
vector(int n); | 将容器初始化成有n个元素 |
vector(int n,const T&val); | 假定元素类型是T,将容器初始化成有n个元素,每个元素的值都是Val |
vector(iterator first,iterator last); | 将容器初始化为与别的容器上区间[first,last)一致的内容 |
void pop_back(); | 删除容器末尾的元素 |
void push_back(const T&val); | 将val添加到容器末尾 |
int size(); | 返回容器中元素的个数 |
T&font(); | 返回容器中第一个元素的引用 |
T&back(); | 返回容器中最后一个元素的引用 |
成员函数:
成员函数 | 作用 |
---|---|
push_front | 在链表最前面插入 |
pop_front | 删除链表最前面的元素 |
sort | 排序(list不支持STL的算法sort) |
remove | 删除和指定值相等的所有元素 |
unique | 删除所有和前一个元素相同的元素 |
merge | 合并两个链表,并清空被合并的链表 |
reverse | 颠倒链表 |
splice | 在指定位置前面插入另一链表中的一个或多个元素,并在另一链表中删除被插入的元素 |
双向队列
必须包含头文件#include
成员函数:
set,multiset,map,multimap
map/multimap容器里放着的都是pair模版类的对象,且按first从小到大排序
template<class _T1, class _T2>
struct pair{
typedef_T1 first type;
typedef_T2 second_type;
T1 first;
T2 second;
pair(): first(), second(){}
pair(const _T1&a, const_T2&b) : first(_a), second(b){}
template<class _U1, class _U2>
pair(const pair<_U1,_U2>&p) : first(p. first), second(p. second){}
实现 :
template<class Key,class Pred=less\<Key\>,class A=allocator<Key>>
class multiset{.....};
Pred类型的变量决定了multiset中的元素,“一个比另一个小”是怎么定义的。
multiset运行过程中,比较两个元素x,y的大小的做法,就是生成一个Pred类型的变量,假定为op,若表达式op(x,y)返回值为true,则x比y小。
Pred的缺省类型是less
其中less模板定义:
template<class T>
struct less:public binary_function<T,T,bool>
{bool operator()(const T& x,const T& y){returnx<y;}const;};
成员函数 :
成员函数 | 作用 |
---|---|
iterator find(const T&val); | 在容器中查找值为val的元素,返回其迭代器.如果找不到,返回end(). |
iterator insert(const T&val); | 将val插入到容器中并返回其迭代器. |
void insert(iterator first,iterator last); | 将区间[first,last)插入容器. |
int count(const T&val); | 统计有多少个元素的值和val相等. |
iterator lower bound(const T&val); | 查找一个最大的位置it,使得[begin(),it),中所有的元素都比val小. |
iterator upper bound(const T&val); | 查找一个最小的位置t,使得[t,end())中所有的元素都比val大. |
pair |
同时求得lower_bound和upper_bound. |
iterator erase(iterator it); | 删除it指向的元素,返回其后面的元素的迭代器(Visual studio2010上如此,但是在cpp标准和Dev cpp中,返回值不是这样). |
实现 :
template<class Key,class Pred=less\<Key\>,class A=allocator<Key>>
class set{...}
插入set中已有的元素时,忽略插入,重复的定义 : (a 。
插入函数的不同
template<typename T>
pair<std::set<T>::iterator,bool> insert(const T&val); 将val插入到容器中并返回其迭代器。
实现 :
template<class Key,class T,class Pred=less\<Key\>,classA=allocator<T>>
class multimap{
..
typedef pair<const Key,T> value_type;
...…
};//Key代表关键字的类型
示例:
# include
# include
using namespace std;
int main(){
typedef multimap<int, double, less<int>>mmid;
mmid pairs;
pairs.insert(mmid: value_type(15,2.7);
cout<<"含有15元素个数:"<<pairs.count(15)<< endl;
实现 :
template<class Key,class T,class Pred=less\<Key\>, class A=allocator<T>>
class map{
... ...
typedef pair<const Key,T> value_type;
... ...
};
若pairs为map模版类的对象
实现
bitset template<size_tN>
class bitset
{
......
};
特性
成员函数
可以用某种顺序容器来实现
(让已有的顺序容器以栈/队列的方式工作)
都有3个成员函数:
实现 :
template<class T,class Cont=deque<T>>
class stack{
...
};
实现 :
template<class T,class Cont=deque<T>>
class queue{
};