第十六章 string类和标准模板库(2. 标准模板库之容器)

标准模板库(STL)提供了一组表示容器、迭代器、函数对象和算法的模板。STL不是面向对象的编程,而是一种编程模式——泛型编程。

面向对象编程关注的是编程的数据方面,而泛型编程关注的是算法。

容器模板类

STL具有容器概念和容器类型。概念是一种通用类别(如,基本容器、序列容器、关联容器等);容器类型是可用于创建具体容器对象的模板。

下面以概念为线索展开

一、基本容器

容器概念指定了所有STL容器类都必须满足一系列要求:

1. 容器是存储其它对象的对象,存储在容器类对象中的对象(内置类型或OOP意义上的对象)必须是同质的。容器类对象过期时,存储在其中的对象也将过期。

2. 存储在容器类对象中的对象必须是可复制构造的和可赋值的(这些作为元素的对象的类必须定义赋值和复制构造函数)。

3. 所有容器都提供了某些特征和操作(但基本容器不能保证其元素都按特定的顺序存储,也不能保证元素的顺序不变)。

二、序列容器

通过添加要求改进基本容器概念。序列是一种重要改进(满足此概念的容器类型有7种),增加的要求如下(有插入、删除等操作):

序列的可选要求

7种容器序列之间的关系:

vector(计算机矢量)

vector<string> words(4); //将woords初始化为4个string类型的矢量

vector提供了自动内存管理功能,模板类型参数指定了使用哪种分配器对象管理内存,默认使用allocator<T>类(T为模板定义的类型),这个类使用new和delete。

支持随机访问,支持以固定时间在矢量尾插入和删除元素。

vector是可反转容器概念的模型,此概念有两个类方法:rbegin()和rend()。

deque(双端队列)

 支持随机访问,并且支持以固定时间在deque对象的开始和末尾插入和删除对象。

list(双向链表)

在list对象的任何位置插入和删除元素的时间都是固定的。

vector强调的是快速访问,而list强调的是快速插入和删除。

list也是可反转容器概念的模型。

list不支持数组表示法([ ])和随机访问。

list模板类中包含双向链表的专用成员函数(未注明的复杂度都为线性):

~链表合并:void merge(list<T, Alloc>&x); //合并后x为空

~从链表中删除val的所有实例:void remove(const T & val);

~使用‘<’运算符对链表进行排序:void sort(); //时间复杂度为NlogN

~将链表内容插入到迭代器pos前面:void splice(iterator pos, list<T, Alloc>x); //插入之后x为空

~将连续的相同元素压缩为单个元素:void unique();

 queue(队列)

 queue模板类是一个适配器,让底层类(deque)展示典型的队列接口。

不允许随机访问队列元素,不允许遍历队列。

queue的使用限制在队列的基本操作上(将元素添加到队尾,从队首删除元素,查看队首和队尾的值,检查元素数目,测试队列是否为空):

 bool empty()const;

size_type size()const;

T & front();

T & back();

void push(const T & x);

void pop();

priority_queue

是一个适配器类,默认的底层是vector。支持的操作与queue类似,只是默认将最大元素移到队首。

提供一个可选的构造函数参数:

priority_queue<int> pd1;

priority_queue<int> pd2(greater<int>); //greater<int>是一个预定义的用于比较的函数对象

stack

是一个适配器类,底层类在默认情况下是vector。

stack模板的限制比vector多,不支持随机访问和遍历。

使用限制在使用栈的基本操作上:

~查看栈是否为空:bool empty()const;

~查看元素数目:sizet_type size();

~返回指向栈顶元素的引用:T & top();

~在栈顶部插入x:void pop(const T & x);

~删除栈顶元素:void pop();

三、关联容器

关联容器将值与键关联在一起,是某种树的实现,有比链表更高的访问速度。

对于关联容器X,X::value_type存储了容器的值类型;X::key_type存储了容器的键类型。

关联容器允许插入新元素,但不能指定元素位置(因为关联容器有确定元素访问位置的算法)。

set / multiset

存储在头文件set中,键与值相同,multiset允许集合中存在相同的值。

set模拟了关联、反转、排序、键唯一的概念。

set的第二个模板参数是可选的,指示用来对键进行排序的比较函数或对象(默认使用模板less<>)。

set也有一个将迭代器区间作为参数的构造函数。

 集合的标准操作:

~注:以下这些函数并不是方法而是通用函数,使用这些函数的先决条件是容器必须是经过排序的,set对象自动满足这一条件。

~并集:1. set_union(A.begin(), A.end(), B.begin(), B.end(), ostream_iterator< string, char > out(cout, " ") ); //最后一个参数是输出迭代器

     2. set_union(A.begin(), A.end(), B.begin(), B.end(), insert_iterator< set<string> > ( C, C.begin() ) ); //将并集插入到C.begin()指示的位置处

~交集:set_intersection();

~差集:set_difference();

~以下为set的方法

~lower_bound(); //将键作为参数,返回指向第一个不小于键参数的迭代器;

~upper_bound(); //将键作为参数,返回指向第一个大于键参数的迭代器。

map / multimap

map是反转和排序的概念模型,但键和值的类型不同。multimap的同一个键可以与多个值关联。

创建multimap对象:

multimap<int, string> codes; //也有第三个可选参数,用于指出对键进行排序的比较函数或对象

STL模板类pair<class T, class U>将键和值存储在一个对象中:

pair<const int, string> item(213, "Los");

code.insert(item); //因为数据是按键排序的,所以不需要指出插入位置。

对于pair对象,可以使用first和second成员来访问其两个部分:

item.first; //返回键

item.second; //返回值

获取multimap对象的信息:

~将键作为参数,返回该键元素的数目:count();

~lower_bound; upper_bound(); //与set相同

~将键作为区间,返回该键所在迭代器区间:equal_range(); //返回的值封装在一个pair对象中,这里的pair模板两个类型参数都是multimap迭代器。

pair< multimap<int string>::iterator, multimap<int string>::iterator > range = code.equal_range(718);

原文地址:https://www.cnblogs.com/sungnox/p/7701797.html