C++ STL

2023/06/10 C++ 共 7999 字,约 23 分钟
闷骚的程序员

什么是STL

c++提供了一个基于模板实现的标准模板库(Standard Template Library,STL)

STL包含了:

  1. 容器类模板

    容器用于存储序列化的数据,如:向量、队列、栈、集合等。

  2. 算法模板

    算法用于对容器中的数据元素进行一些常用操作,如:排序、统计等。

  3. 迭代器类模板

    迭代器实现了抽象的指针功能,他们指向容器中的数据元素,用于对容器中的数据元素进行遍历和访问。传给算法的不是容器,而是指向容器中元素的迭代器。

各容器迭代器的类型

  • 对于vector、deque以及string容器类,他们使用的迭代器类型为随机访问迭代器

  • 对于list、map/mulitmap以及set/multiset容器类,他们使用的迭代器类型为双向迭代器

queue、stack和priority_queue容器类,不支持迭代器。

容器类型

一 string类型

1.string构造函数

string();
//创造一个空的字符串
string(str);
//拷贝构造函数,使用一个string对象初始化另一个sring对象
string(const char* c);
//使用c风格字符串初始化
string(int n,char c);
//使用n个字符c初始化

2.assign成员函数

string& assign(const char* s); 
// C风格字符串赋值给当前的字符串
string& assign(const char* s, int n); 
// 把C风格字符串s的前n个字符赋给当前的字符串
string& assign(const string& s); 
// 把字符串s赋给当前字符串
string& assign(int n, char c); 
// 把n个字符c赋给当前的字符串
string& assign(const string& s, int start, int n); 
// 将字符串s中从start开始的n个字符赋值给当前字符串

3.append成员函数

string& append(const char* s); 
// 把C风格字符数组s连接到当前字符串结尾
string& append(const char* s, int n); 
// 把C风格字符数组s的前n个字符连接到当前字符串结尾
string& append(const string &s); 
// 将字符串s追加到当前字符串末尾
string& append(const string&s, int pos, int n); 
// 把字符串s中从pos开始的n个字符连接到当前字符串结尾
string& append(int n, char c); 
// 在当前字符串结尾添加n个字符c

二 vector类型

1.构造函数

vector<T> v; // 采用模版类实现,默认构造函数
vector<T> v(T* v1.begin(), T* v1.end()); // 将v1[begin(), end())区间中的元素拷贝给本身
vector<T> v(int n, T elem); // 将n个elem拷贝给本身
vector<T> v(const vector<T> v1); // 拷贝构造函数

2.赋值操作

assign(b.begin(), b.end()); // 将[beg, end)区间中的数据拷贝复制给本身
assign(n, elem); // 将n个elem拷贝给本身
vector& operator=(const vector& vec); // 重载赋值操作符
swap(vec); //将vec与本身的元素互换

3.大小操作

int size(); // 返回容器中的元素个数
bool empty(); // 判断容器是否为空

void resize(int num); 
// 重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
// 若容器变短,则末尾超出容器长度的元素被删除
void resize(int num, T elem); 
// 重新指定容器的长度为num,若容器变长,则以elem填充新位置。
// 若容器变短,则末尾超出容器长度的元素被删除

int capacity(); // 返回容器的容量
void reserve(int len); 
// 容器预留len个元素长度,预留位置不初始化,元素不可访问

4.数据存储操作

T& at(int idx); // 返回索引idx所指的数据,如果idx越界,抛出out_of_range异常
T& operator[](int idx); // 返回索引idx所指的数据,如果idx越界,运行直接报错

T& front(); // 返回首元素的引用
T& back(); // 返回尾元素的引用

5.插入和删除操作

insert(const_iterator pos, T elem); // 在pos位置处插入元素elem
insert(const_iterator pos, int n, T elem); // 在pos位置插入n个元素elem
inser(const_iterator pot ,const_iterator beg,const_iterator end); // 将[beg, end)区间内的元素插到位置pos
push_back(T elem); // 尾部插入元素elem
pop_back(); // 删除最后一个元素
//随机迭代器的特性
erase(const_iterator start, const_iterator end); // 删除区间[start, end)内的元素
erase(const_iterator pos); // 删除位置pos的元素

clear(); // 删除容器中的所有元素

三 deque双向队列容器

1.构造函数

deque<T> deqT; // 默认构造函数
deque(beg, end); // 构造函数将[beg, end)区间中的元素拷贝给本身
deque(int n, T elem); // 构造函数将n个elem拷贝给本身
deque(const deque& deq); // 拷贝构造函数

2.赋值操作

assign(beg, end); // 将[beg, end)区间中的元素拷贝赋值给本身
assign(int n, T elem); // 将n个元素elem拷贝赋值给本身

deque& operator=(const deque& deq); // 重载赋值操作符

swap(deq); // 将deq与本身的元素互换

3.大小操作

int size(); // 返回容器中元素的个数
bool empty(); // 判断容器是否为空

void resize(int num); 
// 重新指定容器的长度为num,若容器变长,则以默认值填充新位置,
// 如果容器变短,则末尾超出容器长度的元素被删除
void resize(int num, T elem);
// 重新指定容器的长度为num,若容器变长,则以elem填充新位置,
// 如果容器变短,则末尾超出容器长度的元素被删除

4.数据存取

T& at(int idx); // 返回索引idx所指的数据,如果idx越界,抛出out_of_range异常
T& operator[](int idx); // 返回索引idx所指的数据,如果idx越界,运行直接报错

T& front(); // 返回首元素的引用
T& back(); // 返回尾元素的引用

5.数据插入和删除

const_iterator insert(const_iterator pos, T elem); 
// 在pos位置处插入元素elem的拷贝,返回新数据的位置
void insert(const_iterator pos, int n, T elem); 
// 在pos位置插入n个元素elem,无返回值
void insert(pos, beg, end);
// 将[beg, end)区间内的元素插到位置pos,无返回值
clear(); // 移除容器的所有数据
iterator erase(iterator beg, iterator end);
// 删除区间[beg, end)的数据,返回下一个数据的位置
iterator erase(iterator pos)// 删除pos位置的数据,返回下一个数据的位置

push_back(T elem); // 在容器尾部添加一个元素
push_front(T elem); // 在容器头部插入一个元素

pop_back(); // 删除容器最后一个数据
pop_front(); // 删除容器第一个数据

四 stack容器—不允许遍历行为,因为没有迭代器

1.构造函数

stack<T> stkT; // 默认构造函数,stack采用模版类实现
stack(const stack& stk); // 拷贝构造函数

2.赋值操作

stack& operator=(const stack& stk); // 重载赋值操作符

3.数据存取

void push(T elem); // 向栈顶添加元素
void pop(); // 从栈顶移除第一个元素
T& top(); // 返回栈顶元素

4.大小操作

bool empty(); // 判断堆栈是否为空
int size(); // 返回栈的大小

五 queue队列—不允许遍历行为,因为没有迭代器

1.构造函数

queue<T> queT; // queue对象的默认构造函数形式,采用模版类实现
queue(const queue& que); // 拷贝构造函数

2.赋值操作

queue& operator=(const queue& que); // 重载赋值操作符

3.数据存取

void push(T elem); // 往队尾添加元素
void pop(); // 从队头移除第一个元素
T& back(); // 返回最后一个元素
T& front(); // 返回第一个元素

4.大小操作

bool empty(); // 判断队列是否为空
int size(); // 返回队列的大小

六 list链表-不支持随机访问

1.遍历

for(list<T>::iterator it = lst.begin(); it != lst.end(); it++)
{
    cout << *it << endl;
}

2.构造函数

list<T> lstT; // 默认构造形式,list采用模版类实现
list(beg, end); // 构造函数将[beg, end)区间内的元素拷贝给本身
list(int n, T elem); // 构造函数将n个elem拷贝给本身
list(const list& lst); // 拷贝构造函数

3.数据插入和删除

void push_back(T elem); // 在容器尾部加入一个元素
void pop_back(); // 删除容器中最后一个元素

void push_front(T elem); // 在容器开头插入一个元素
void pop_front(); // 从容器开头移除第一个元素

insert(iterator pos, elem); // 在pos位置插入elem元素的拷贝,返回新数据的位置
insert(iterator pos, n, elem); // 在pos位置插入n个elem元素的拷贝,无返回值
insert(iterator pos, beg, end); // 在pos位置插入[beg, end)区间内的数据,无返回值

void clear(); // 移除容器的所有数据

erase(beg, end); // 删除[beg, end)区间内的所有数据,返回下一个数据的位置
erase(pos); // 删除pos位置的数据,返回下一个数据的位置

remove(elem); // 删除容器中所有与elem匹配的元素

4.大小操作

int size(); // 返回容器中元素的个数
bool empty(); // 判断容器是否为空

void resize(int num);
// 重新制定容器的长度为num,若容器变长,则以默认值填充新位置;
// 若容器变短,则末尾超出容器长度的元素被删除
void resize(int num, T elem);
// 重新制定容器的长度为num,若容器变长,则以elem填充新位置;
// 若容器变短,则末尾超出容器长度的元素被删除

5.赋值操作

assign(beg, end); // 将[beg, end)区间中的数据拷贝赋值给本身
assign(n, elem); // 将n个elem拷贝赋值给本身

list& operator=(const list& lst); // 重载等号操作符

swap(lst); // 将lst与本身的元素互换

6.数据存取

T& front(); // 返回第一个元素
T& back(); // 返回最后一个元素

7.反转排序

void reverse(); // 反转链表

void sort(); // 默认list排序,规则为从小到大
void sort(bool (*cmp)(T item1, T item2)); // 指定排序规则的list排序

// 不能用sort(lst.begin(), lst.end())
// 因为所有系统提供的某些算法(比如排序),其迭代器必须支持随机访问
// 不支持随机访问的迭代器的容器,容器本身会对应提供相应的算法的接口

七 set/multiset-集合

  • multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复。

  • set和multiset的底层实现是红黑树,红黑树为平衡二叉树的一种

  • set的特性是,所有的容器都会根据元素自身的键值进行自动被排序。

  • set不允许两个元素有相同的键值

1.遍历

for (set<T>::iterator it = s.begin(); it != s.end(); it++)
{
      cout << *it << endl;
}

2.构造函数

set<T> st; // set 默认构造函数
multiset<T> mst; // multiset 默认构造函数
set(const set& st); // 拷贝构造函数

3.赋值操作

set& operator=(const set& st); // 重载等号操作符

swap(st); // 交换两个集合容器

4.大小操作

int size(); // 返回容器中元素的数目
bool empty(); // 判断容器是否为空

5.插入和删除操作

pair<iterator, bool> insert(T elem); 
// 在容器中插入元素,返回插入位置的迭代器(不成功则返回end())和是否插入成功
// 如果是multiset,则返回值只有iterator
clear(); // 清除所有元素
iterator erase(pos); // 删除pos迭代器所指的元素,返回下一个元素的迭代器
iterator erase(beg, end); // 删除区间[beg, end)内的所有元素,返回下一个元素的迭代器
erase(T elem); // 删除容器中值为elem的元素

6.查找操作

iterator find(T key); 
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
int count(T key);
// 查找键key的元素个数
iterator lower_bound(T keyElem);
// 返回第一个key>=keyElem元素的迭代器
iterator upper_bound(T keyElem);
// 返回第一个key>keyElem元素的迭代器
pair<iterator, iterator> equal_range(T keyElem);
// 返回容器中key与keyElem上相等的两个上下限迭代器

八 map/multimap-映射

map 的特性是,所有的元素都会根据元素的键值自动排序;

map 的所有元素都是pair,同时拥有实值和键值。

  • pair的第一元素被视为键值,第二元素被视为实值;

  • map不允许两个元素有相同的键值;

和set类似的原因,我们不能通过迭代器改变map的键值,但我们可以任意修改实值。

map和list在增删元素的时候具有相似的性质。

map和multimap的操作类似,唯一的区别是multimap键值可重复。

map和multimap都是以红黑树作为底层实现机制。

1.遍历

for (map<T1, T2>::iterator it = m.begin(); it != m.end(); it++)
{
    cout << "key = " << it->first << " value = " << it->second << endl;
}

2.构造函数

map<T1, T2> mapTT; // map默认构造函数
map(const map& mp); // 拷贝构造函数

3.赋值操作

map& operator=(const map& mp); // 重载等号操作符
swap(mp); // 交换两个集合容器

4.大小操作

int size(); // 返回容器中元素的数目
bool empty(); // 判断容器是否为空

5.插入和删除

pair<iterator, bool> insert(pair<T1, T2> p); // 通过pair的方式插入对象
/*
1. 参数部分可以用pair的构造函数创建匿名对象
2. 也可以使用make_pair创建pair对象
3. 还可以用map<T1, T2>::value_type(key, value)来实现
*/

T2& operator[](T1 key); // 通过下标的方式插入值
// 如果通过下标访问新的键却没有赋值,会自动用默认值填充
void clear(); // 删除所有元素
iterator erase(iterator pos); // 删除pos迭代器所指的元素,返回下一个元素的迭代器
iterator erase(beg, end); // 删除区间[beg, end)内的所有元素,返回下一个元素的迭代器
erase(keyElem); // 删除容器中key为keyElem的对组

6.查找操作

iterator find(T1 key); 
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end()
int count(T1 keyElem);
// 返回容器中key为keyElem的对组个数,对map来说只可能是0或1,对于multimap可能大于1

iterator lower_bound(T keyElem);
// 返回第一个key>=keyElem元素的迭代器
iterator upper_bound(T keyElem);
// 返回第一个key>keyElem元素的迭代器
pair<iterator, iterator> equal_range(T keyElem);
// 返回容器中key与keyElem上相等的两个上下限迭代器

九 unordered_map

不允许有重复的键值对

find(key);//寻找容器内key=key的元素,如果找到元素则返回迭代器
//未找到的话返回指向end()的迭代器。
emplace(key,value);//无需手动创建key-value,内部会自动完成此操作。
emplace_back();
int count(t(T1 keyElem);

十 unordered_set

unordered_set不是以键值对的形式存储数据,而是直接存储数据的值


十一 priority_queue

priority_queue<int,vector<int>,less<int>>

int:数据类型

vector:用什么容器存储

greater:大顶堆,顺序

文档信息

Search

    Table of Contents