STL指的是C++的标准模板库,是一个C++软件库,大量影响了C++标准程序库,但是不是C++标准程序库的一部恩。STL包括了4个组件:算法,容器,函数,迭代。
第一个常用容器是vector。向量是一个封装了动态大小数组的顺序容器。跟任意其它类型容易一样,可以放置任何类型的对象。因此,可以简单的认为向量是一个能够存放任意类型的动态数组。Vector支持随机访问,但是不支持任意位置的O(1)插入,通常在末尾进行插入。
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> a({1,2,3});
//用角标遍历
for (int i=0; i<a.size();i++){
cout << a[i] << endl;
}
//用迭代器遍历
for (vector<int>::iterator i = a.begin();i!=a.end();i++){
cout << *i << endl;
}
//front()函数可以直接范围vector的第一个元素的值,*begin也可是实现这一点
cout << a.front() << ' ' << a[0] << ' ' << *a.begin() << endl;
//back()函数可以直接范围vector的最后一个元素的值
cout << a.back() << ' ' << a[a.size()-1] << endl;
return 0;
}
vector中常用的删减函数为:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> a({1,2,3});
//push_back()函数可以在vector的末尾添加上元素
a.push_back(4);
for (auto x: a) cout << x << " ";
cout << endl;
//pop_back则可以删除vector末尾的元素
a.pop_back();
for (auto x: a) cout << x << " ";
cout << endl;
//再次删除
a.pop_back();
for (auto x: a) cout << x << " ";
cout << endl;
return 0;
}
第二个常用的容器是队列(queue)。头文件queue主要包括循环队列queue和优先队列(priority queue)。队列的性质是:先进先出。首先插入的元素将首先被提取,依此类推。有一个称为“前”的元素,它是位于最前位置或位于第一个位置的元素,也有一个名为“后”的元素,它是位于最后位置的元素。在普通队列中,元素的插入在尾部,而删除则从前面开始。优先队列在弹出数据的时候会优先弹队列中的最大值。
容器应支持以下操作列表:
- empty
- size
- push_back
- pop_front
- front
- back
函数 | 描述 |
(constructor) | 该函数用于构造队列容器。 |
empty | 该函数用于测试队列是否为空。如果队列为空,则该函数返回true,否则返回false。 |
size | 该函数返回队列中元素的个数。 |
front | 该函数返回第一个元素。元素起着非常重要的作用,因为所有的删除操作都是在front元素上执行的。 |
back | 该函数返回最后一个元素。该元素起着非常重要的作用,因为所有插入操作都在后面元素上执行。 |
push | 该函数用于在末尾插入一个新元素。 |
pop | 该函数用于删除第一个元素。 |
emplace | 该函数用于在当前后元素上方的队列中插入新元素。 |
swap | 该函数用于交换参考中两个容器的内容。 |
relational operators | 非成员函数指定队列所需的关系运算符。 |
uses allocator<queue> | 顾名思义,非成员函数将分配器用于队列。 |
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int main(){
queue<int> q;//队列
q.push(1);//会在队尾插入一个元素
q.pop();//会弹出对头元素
q.front();//返回队头元素
q.back();//返回队尾巴
priority_queue<int> a;//优先队列
a.top();//取得一个最大值
a.pop();//删除最大值
//如何清空队列
q = queue<int>();//重新初始化一个队列
return 0;
}
第三个常用的容器是栈。这种数据结构使用LIFO技术,其中LIFO表示后进先出。首先插入的元素将在末尾提取,以此类推。有一个名为“top”的元素,它是位于最上面位置的元素。所有插入和删除操作都是在堆栈的顶部元素本身进行的。
函数 | 描述 |
(constructor) | 该函数用于构造堆栈容器。 |
empty | 该函数用于测试堆栈是否为空。如果堆栈为空,则该函数返回true,否则返回false。 |
size | 该函数返回堆栈容器的大小,该大小是堆栈中存储的元素数量的度量。 |
top | 该函数用于访问堆栈的顶部元素。该元素起着非常重要的作用,因为所有插入和删除操作都是在顶部元素上执行的。 |
push | 该函数用于在堆栈顶部插入新元素。 |
pop | 该函数用于删除元素,堆栈中的元素从顶部删除。 |
emplace | 该函数用于在当前顶部元素上方的堆栈中插入新元素。 |
swap | 该函数用于交换引用的两个容器的内容。 |
relational operators | 非成员函数指定堆栈所需的关系运算符。 |
#include <iostream>
#include <stack>
using namespace std;
void newstack(stack <int> ss)
{
stack <int> sg = ss;
while (!sg.empty())
{
cout << '\t' << sg.top();
sg.pop();
}
cout << '\n';
}
int main ()
{
stack <int> newst;
newst.push(55);
newst.push(44);
newst.push(33);
newst.push(22);
newst.push(11);
cout << "最新的堆栈是 : ";
newstack(newst);
cout << "\n newst.size() : " << newst.size();
cout << "\n newst.top() : " << newst.top();
cout << "\n newst.pop() : ";
newst.pop();
newstack(newst);
return 0;
}
第四个常用的容器是set容器。set 是关联容器的一种,是排序好的集合(元素已经进行了排序)。set 和 multiset 类似,它和 multiset 的差别在于 set 中不能有重复的元素。multiset 的成员函数 set 中也都有。不能直接修改 set 容器中元素的值。因为元素被修改后,容器并不会自动重新调整顺序,于是容器的有序性就会被破坏,再在其上进行查找等操作就会得到错误的结果。因此,如果要修改 set 容器中某个元素的值,正确的做法是先删除该元素,再插入新元素。
使用 set 必须包含头文件 <set>。set 的定义如下:
template < class Key, class Pred = less<Key>, class A = allocator<Key> > class set {...}
由于不能有重复元素,所以 set 中插入单个元素的 insert 成员函数与 multiset 中的有所不同,其原型如下:
pair<iterator, bool> insert(const T & val);
如果 set 的 insert 成员函数的返回值是 pair 模板类对象 x,如果 x.second 为 true,则说明插入成功,此时 x.first 就是指向被插入元素的迭代器;如果 x.second 为 false,则说明要插入的元素已在容器中,此时 x.first 就是指向原有那个元素的迭代器。
关联容器的 equal_range 成员函数的返回值也是 pair 模板类对象,其原型如下:
pair<iterator, iterator> equal_range(const T & val);
回值对象中的 first 就是 lower_bound 的值,second 就是 upper_bound 的值。
下面的程序演示了 set 的用法。
#include <iostream>
#include <set> //使用set须包含此文件
using namespace std;
int main()
{
typedef set<int>::iterator IT;
int a[5] = { 3,4,6,1,2 };
set<int> st(a,a+5); // st里是 1 2 3 4 6
pair< IT,bool> result;
result = st.insert(5); // st变成 1 2 3 4 5 6
if(result.second) //插入成功则输出被插入元素
cout << * result.first << " inserted" << endl; //输出: 5 inserted
if(st.insert(5).second)
cout << * result.first << endl;
else
cout << * result.first << " already exists" << endl;
//输出 5 already exists
pair<IT,IT> bounds = st.equal_range(4);
cout << * bounds.first << "," << * bounds.second ; //输出:4,5
return 0;
}