vector 容器
vector 是顺序容器的一种。vector 是可变长的动态数组,支持随机访问迭代器,所有 STL 算法都能对 vector 进行操作。要使用 vector,需要包含头文件 vector。
表:vector中常用的成员函数
成员函数 | 作 用 |
---|---|
vector() | 无参构造函数,将容器初始化为空 |
vector(int n) | 将容器初始化为有 n 个元素 |
vector(int n, const T & val) | 假定元素的类型是 T,此构造函数将容器初始化为有 n 个元素,每 个元素的值都是 val |
vector(iterator first, iterator last) | first 和 last 可以是其他容器的迭代器。一般来说,本构造函数初始化的结果就是将 vector 容器的内容变成与其他容器上的区间 [first, last) —致 |
void clear() | 删除所有元素 |
bool empty() | 判断容器是否为空 |
void pop_back() | 删除容器末尾的元素 |
void push_back( const T & val) | 将 val 添加到容器末尾 |
int size() | 返回容器中元素的个数 |
T & front() | 返回容器中第一个元素的引用 |
T & back() | 返回容器中最后一个元素的引用 |
iterator insert(iterator i, const T & val) | 将 val 插入迭代器 i 指向的位置,返回 i |
iterator insert( iterator i, iterator first, iterator last) | 将其他容器上的区间 [first, last) 中的元素插入迭代器 i 指向的位置 |
iterator erase(iterator i) | 删除迭代器 i 指向的元素,返回值是被删元素后面的元素的迭代器 |
iterator erase(iterator first, iterator last) | 删除容器中的区间 [first, last) |
void swap( vector & v) | 将容器自身的内容和另一个同类型的容器 v 互换 |
vector 的基本用法:
#include <iostream>
#include <vector> //使用vector需要包含此头文件
using namespace std;
template <class T>
void PrintVector(const vector <T> & v)
{ //用于输出vector容器的全部元素的函数模板
typename vector <T>::const_iterator i;
//typename 用来说明 vector <T>::const_iterator 是一个类型,在 Visual Studio 中不写也可以
for (i = v.begin(); i != v.end(); ++i)
cout << *i << " ";
cout << endl;
}
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
vector <int> v(a, a + 5); //将数组a的内容放入v
cout << "1) " << v.end() - v.begin() << endl; //两个随机迭代器可以相减,输出:1)5
cout << "2)"; PrintVector(v); //输出:2)1 2 3 4 5
v.insert(v.begin() + 2, 13); //在 begin()+2 位置插人 13
cout << "3)"; PrintVector(v); //输出:3)1 2 13 3 4 5
v.erase(v.begin() + 2); //删除位于 begin()+2 位置的元素
cout << "4)"; PrintVector(v); //输出:4)1 2 3 4 5
vector<int> v2(4, 100); //v2 有 4 个元素,都是 100
v2.insert(v2.begin(), v.begin() + 1, v.begin() + 3); //将v的一段插入v2开头
cout << "5)v2:"; PrintVector(v2); //输出:5)v2:2 3 100 100 100 100
v.erase(v.begin() + 1, v.begin() + 3); //删除 v 上的一个区间,即 [2,3)
cout << "6)"; PrintVector(v); //输出:6)1 4 5
return 0;
}
list
list 是顺序容器的一种。list 是一个双向链表。使用 list 需要包含头文件 list。
list 容器不支持根据下标随机存取元素。
list 的构造函数和许多成员函数的用法都与 vector 类似。除了顺序容器都有的成员函数外,list 容器还独有如表所示的成员函数(此表不包含全部成员函数,且有些函数的参数较为复杂,表中只列出函数名)。
表:list 的成员函数
成员函数或成员函数模板 | 作 用 |
---|---|
void push_front(const T & val) | 将 val 插入链表最前面void pop_front()删除链表最前面的元素 |
void sort() | 将链表从小到大排序 |
void remove (const T & val) | 删除和 val 相等的元素remove_if |
void unique() | 删除所有和前一个元素相等的元素 |
void merge(list & x) | 将链表 x 合并进来并清空 x。要求链表自身和 x 都是有序的 |
void splice(iterator i, list & x, iterator first, iterator last) | 在位置 i 前面插入链表 x 中的区间 [first, last),并在链表 x 中删除该区间。链表自身和链表 x 可以是同一个链表,只要 i 不在 [first, last) 中即可 |
表中列出的成员函数有些是重载的,如 unique、merge、splice 成员函数都不止一个。
STL 中的算法 sort 可以用来对 vector 和 deque 排序,它需要随机访问迭代器的支持。因为 list 不支持随机访问迭代器,所以不能用算法 sort 对 list 容器排序。因此,list 容器引入了 sort 成员函数以完成排序。
list 的示例程序如下:
#include <list> //使用 list 需要包含此头文件
#include <iostream>
#include <algorithm> //使用STL中的算法需要包含此头文件
using namespace std;
class A {
private: int n;
public:
A(int n_) { n = n_; }
friend bool operator < (const A & a1, const A & a2);
friend bool operator == (const A & a1, const A & a2);
friend ostream & operator << (ostream & o, const A & a);
};
bool operator < (const A & a1, const A & a2) {
return a1.n < a2.n;
}
bool operator == (const A & a1, const A & a2) {
return a1.n == a2.n;
}
ostream & operator << (ostream & o, const A & a) {
o << a.n;
return o;
}
template <class T>
void Print(T first, T last)
{
for (; first != last; ++first)
cout << *first << " ";
cout << endl;
}
int main()
{
A a[5] = { 1, 3, 2, 4, 2 };
A b[7] = { 10, 30, 20, 30, 30, 40, 40 };
list<A> lst1(a, a + 5), lst2(b, b + 7);
lst1.sort();
cout << "1)"; Print(lst1.begin(), lst1.end()); //输出:1)1 2 2 3 4
lst1.remove(2); //删除所有和A(2)相等的元素
cout << "2)"; Print(lst1.begin(), lst1.end()); //输出:2)1 3 4
lst2.pop_front(); //删除第一个元素
cout << "3)"; Print(lst2.begin(), lst2.end()); //输出:3)30 20 30 30 40 40
lst2.unique(); //删除所有和前一个元素相等的元素
cout << "4)"; Print(lst2.begin(), lst2.end()); //输出:4)30 20 30 40
lst2.sort();
lst1.merge(lst2); //合并 lst2 到 lst1 并清空 lst2
cout << "5)"; Print(lst1.begin(), lst1.end()); //输出:5)1 3 4 20 30 30 40
cout << "6)"; Print(lst2.begin(), lst2.end()); //lst2是空的,输出:6)
lst1.reverse(); //将 lst1 前后颠倒
cout << "7)"; Print(lst1.begin(), lst1.end()); //输出 7)40 30 30 20 4 3 1
lst2.insert(lst2.begin(), a + 1, a + 4); //在 lst2 中插入 3,2,4 三个元素
list <A>::iterator p1, p2, p3;
p1 = find(lst1.begin(), lst1.end(), 30);
p2 = find(lst2.begin(), lst2.end(), 2);
p3 = find(lst2.begin(), lst2.end(), 4);
lst1.splice(p1, lst2, p2, p3); //将[p2, p3)插入p1之前,并从 lst2 中删除[p2,p3)
cout << "8)"; Print(lst1.begin(), lst1.end()); //输出:8)40 2 30 30 20 4 3 1
cout << "9)"; Print(lst2.begin(), lst2.end()); //输出:9)3 4
return 0;
}
deque
deque 也是顺序容器的一种,同时也是一个可变长数组。要使用 deque,需要包含头文件 deque。所有适用于 vector 的操作都适用于 deque。
deque 和 vector 有很多类似的地方。在 deque 中,随机存取任何元素都能在常数时间内完成(但慢于vector)。
它相比于 vector 的优点是,vector 在头部删除或添加元素的速度很慢,在尾部添加元素的性能较好,而 deque 在头尾增删元素都具有较好的性能(大多数情况下都能在常数时间内完成)。
它有两种 vector 没有的成员函数:
void push_front (const T & val); //将 val 插入容器的头部
void pop_front(); //删除容器头部的元素
函数对象
如果一个类将()运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象。函数对象是一个对象,但是使用的形式看起来像函数调用,实际上也执行了函数调用,因而得名。
下面是一个函数对象的例子。
#include <iostream>
using namespace std;
class CAverage
{
public:
double operator()(int a1, int a2, int a3)
{ //重载()运算符
return (double)(a1 + a2 + a3) / 3;
}
};
int main()
{
CAverage average; //能够求三个整数平均数的函数对象
cout << average(3, 2, 3); //等价于 cout << average.operator(3, 2, 3);
return 0;
}
STL 中的函数对象类模板
……