C++STL标准模板库容器

本文介绍了C++STL中的各种容器,如array、vector、string、list、map、pair、set、queue、priority_queue、deque以及unordered_map和unordered_set,详细阐述了它们的特点、操作和应用场景。
摘要由CSDN通过智能技术生成

目录

array

vector

string 

迭代器

list

map 

pair键值对

set

queue

priority_queue

deque

unordered_map&unordered_ multimap

unordered_set&unordered_multiset


array

array容器封装了一个静态数组,在栈上分配内存

array类模板定义
template<class T, size_t size>
class array{
private:
	T elems_[size]; 
	……
};

基本操作和vector差不多 

特点:比使用常规数组更方便,因为可以用模板,在设计函数时更便捷

vector

简单说就是一个可以存放任何数据类型的动态数组

在之前文章已经介绍过:leetcode每日一题复盘(8.25~9.1)_看到请催我学习的博客-CSDN博客

string 

string字符容器,一个只能存放字符类型的动态数组

相比于一般的字符数组,string容器有以下优点:

1.不用考虑内存分配和释放的问题

2.动态管理内存

3. 提供了大量API(应用程序接口,可以简单理解为方法)

下面列举string容器常用的函数:

创建对象:

string():创建长度为0的string对象(默认构造函数)

string(const string &str):将对象初始化为str(拷贝构造函数)

string(const string &str,size_t pos=0,size_t n=npos):将对象初始化为str从位置pos到n的字符

赋值操作:

string &operator=(const string &str):重载赋值运算符,将str赋值给当前对象

连接交换比较:

string &operator+=(const string &str):重载+=运算符,实现当前对象与str的连接

void swap(string &str):交换当前对象和str的值

bool operator==(const string &str1,const string &str2) const:重载等于运算符,比较str1和str2是否相等

插入操作:

string& insert(size_t pos, const string& str):在对象pos位置插入str

除了这些还有查找(find),替换(replace)等操作,这些都是在STL中封装好的可以直接使用的函数

迭代器

这里补充一下迭代器(iterator)这个概念,遍历容器很多都用到迭代器

迭代器是访问容器中元素的通用方法,每个容器都有一个迭代器,支持赋值,解引用,比较,遍历等操作的都是迭代器

迭代器分为四类:

正向迭代器:只能用++运算符从左到右遍历容器的元素

容器名<元素类型>::iterator 迭代器名;//正向迭代器

容器名<元素类型>::const_iterator 迭代器名;//常正向迭代器,不可修改

相关函数有:begin(),begin()(const版),cbegin()(迭代器类型为const,想使用auto修饰迭代器对象时使用),end(),end()(const版),cend()

双向迭代器:可以从前往后遍历也可以从后往前遍历

容器名<元素类型>:: reverse_iterator 迭代器名;        // 反向迭代器

容器名<元素类型>:: const_reverse_iterator 迭代器名;  // 常反向迭代器

相关函数有:rbegin(),crbegin(),rend(),crend()

随机访问迭代器:

具备双向迭代器的功能,还支持下标运算,加减法运算,相对位置关系运算

数组的指针就是随机访问迭代器

输入输出迭代器:

不是把容器当做操作对象,而是把输入/输出流作为操作对象

begin()指向第一个元素前一位的地址,end()指向最后一个元素后一位的地址

迭代器失效:

使用resize()、reserve()、assign()、push_back()、pop_back()insert()、erase()等函数会引起vector容器的动态数组发生变化,可能导致vector迭代器失效

迭代器获取的是位置指针,当容器元素发生插入删除等变化时,元素的相对位置和地址可能会发生变化,所以遍历的时候要记得更新迭代器地址


总而言之,迭代器是一种类型,我们通过begin(),end()获取容器地址并赋值给迭代器对象,通过操作迭代器对象完成遍历(for循环),一般情况下是操作指针

list

list容器封装了双链表,使用需要包含头文件#include<list>

list类模板定义
template<class T, class Alloc = allocator<T>>
class list{
private:
	iterator head;
	iterator tail;
	……
}

list容器常用的函数:

构造对象:

list();  // 创建一个空的list容器

list(initializer_list<T> il); // 使用统一初始化列表

list(const list<T>& l);  // 拷贝构造函数

list(Iterator first, Iterator last);  // 用迭代器创建list容器

list(list<T>&& l);  // 移动构造函数

操作元素:

T &front();        // 获取第一个元素

T &back();        // 获取最后一个元素

赋值操作:

list &operator=(const list<T> &l);         // 把容器l赋值给当前容器

list &operator=(initializer_list<T> il);  // 用统一初始化列表给当前容器赋值

交换反转排序归并:

void swap(list<T> &l);   // 把当前容器与l交换,交换的是链表结点的地址

void reverse();           // 反转链表

void sort();              // 对容器中的元素进行升序排序

void merge(list<T> &l);  // 采用归并法合并两个已排序的list容器,合并后的list容器仍是有序的

比较操作:

bool operator == (const vector<T> & l) const;

bool operator != (const vector<T> & l) const;

插入删除:

void push_back(const T& value);  // 在链表的尾部追加一个元素。

void emplace_back(…);           // 在链表的尾部追加一个元素,…用于构造元素。C++11

iterator insert(iterator pos, const T& value);  // 在指定位置插入一个元素,返回指向插入元素的迭代器。

iterator emplace (iterator pos, …);  // 在指定位置插入一个元素,…用于构造元素,返回指向插入元素的迭代器。C++11

iterator insert(iterator pos, iterator first, iterator last);  // 在指定位置插入一个区间的元素,返回指向第一个插入元素的迭代器。

void pop_back();                      // 从链表尾部删除一个元素。

iterator erase(iterator pos);             // 删除指定位置的元素,返回下一个有效的迭代器。

iterator erase(iterator first, iterator last); // 删除指定区间的元素,返回下一个有效的迭代器。)

push_front(const T& value);  // 在链表的头部插入一个元素。

emplace_front(…);          // 在链表的头部插入一个元素,…用于构造元素。C++11

void remove(const T& value);  // 删除链表中所有值等于value的元素。

void unique();                 // 删除链表中相邻的重复元素,只保留一个。

void pop_front();              // 从链表头部删除一个元素。

补充:forward_list (封装了单链表),基本操作与list相同,可以节省一点内存

map 

在介绍map容器前补充一个概念pair键值对

pair键值对

因为树节点的结构中不只存放一个数据(要存放key和value),因此将两个数据存放在一起组成一个结构体

pair是类模板,以结构体的方式实现

pair结构模板定义
template <class T1, class T2>
struct pair 
{ 
    T1 first;     // 第一个成员,一般表示key。
    T2 second;  // 第二个成员,一般表示value。
	pair();       // 默认构造函数。
	pair(const T1 &val1,const T2 &val2);   // 有两个参数的构造函数。
	pair(const pair<T1,T2> &p);           // 拷贝构造函数。
	void swap(pair<T1,T2> &p);           // 交换两个pair。
};

 make_pair函数返回一个pair对象

make_pair函数模板定义
template <class T1, class T2>
make_pair(const T1 &first,const T2 &second)
{
	return pair<T1,T2>(first, second);
}

pair对象相关构造用法:

pair<int, string> p0;//创建空的pair对象

pair<int, string> p1(1, "西施");  //两个参数的拷贝构造函数,支持使用赋值符拷贝构造

auto p4 = pair<int, string>(4, "西施");//匿名对象,让auto推导数据类型

auto p5 = make_pair<int, string>(5, "西施5");//让auto推导数据类型,可以省略make_pair函数的数据类型<int, string>


map容器封装了红黑树(平衡二叉排序树) ,使用时需要include<map>,map元素类型是pair类型

map类定义(树的结构)

template <class K, class V, class P = less<K>, class _Alloc = allocator<pair<const K, V >>>
class map : public _Tree<_Tmap_traits< K, V, P, _Alloc, false>> 
{
      类内部
}
模板参数k是key的数据类型
模板参数v是value的数据类型
模板参数p是排序方法,缺省为升序
模板参数_alloc是分配器,缺省用new,delete

树节点的结构

struct BTNode                        
{                                  
   	pair<K,V> p;       // 键值对。      
	BTNode *parent;   // 父节点。   
	BTNode *lchirld;    // 左子树。 
	BTNode *rchild;    // 右子树。 
};                      

map容器常用的函数:

创建对象:

map();  // 创建一个空的map容器

map(initializer_list<pair<K,V>> il); // 使用统一初始化列表初始化map对象

map(const map<K,V>& m);  // 拷贝构造函数

map(Iterator first, Iterator last);  // 用迭代器创建map容器

访问操作:

V &operator[](K key);// 重载[]运算符,通过key值访问value,有const版本

赋值操作:

map<K,V> &operator=(const map<K,V>& m);  // 重载赋值运算符,将覆盖原有内容

map<K,V> &operator=(initializer_list<pair<K,V>> il);// 重载赋值运算符,将统一初始化列表赋值给对象 

查找操作:

iterator find(const K &key);// 在map容器中查找键值为key的键值对,如果成功找到,则返回指向该键值对的迭代器;失败返回end(),有大于等于key,小于等于key的版本

插入操作

void insert(initializer_list<pair<K,V>> il);  // 用统一初始化列表在容器中插入多个元素

pair<iterator,bool> insert(const pair<K,V> &value);  // 在容器中插入一个元素,返回值pair:first是已插入元素的迭代器,second是插入结果

删除操作:

iterator erase(iterator pos);  // 用迭代器删除元素,返回下一个有效的迭代器

iterator erase(iterator first,iterator last);  // 用迭代器删除一个区间的元素,返回下一个有效的迭代器

补充:multimap(可以同时存储多个key相同的键值对) 

set

与map类似set也是存放键值对(实质上set是存放value),set容器存放key和value相等的键值对,使用set时只需要传入key和value之一

set存放数据时会对数据进行排序,默认是升序排序

set容器中的元素虽然没有const修饰但是不可修改,只能通过删除添加改变元素

set中元素互不相等

set类模板定义:

template < class T,class Compare = less<T>, class Alloc = allocator<T>> 
class set
{
T// 键 key 和值 value 的类型 
C// 指定 set 容器内部的排序规则,缺省为升序
A//指定分配器对象的类型,缺省使用new delete
}
;  
  

set容器常用的函数:

构造对象:

set()// 创建一个空的set对象

set(initializer_list<class T> il)// 用统一初始化列表初始化set对象

set(&set1)// 拷贝构造函数

set(&&set1)// 移动构造函数

还可以用指针进行区间构造

插入操作:

pair<iterator,bool> insert (const value_type& val)//插入val到set容器中,返回值为pair


当向 set 容器添加元素成功时,该迭代器指向 set 容器新添加的元素,bool 类型的值为 true;

如果添加失败,即证明原 set 容器中已存有相同的元素,此时返回的迭代器就指向容器中相同的此元素,同时 bool 类型的值为 false 


iterator insert (const_iterator position, const value_type& val)//指定插入位置的插入操作,返回指向插入的新元素的迭代器

void insert ( {E1, E2,...,En} )// 一次性插入多个元素

template <class... Args>pair<iterator,bool> emplace (Args&&... args)//用于插入数据的类型是类/结构体时,直接传入构建新元素所需的数据即可

template <class... Args>iterator emplace_hint (const_iterator position, Args&&... args)


和 emplace() 方法相比,有以下 2 点不同:

该方法需要额外传入一个迭代器,用来指明新元素添加到 set 容器的具体位置(新元素会添加到该迭代器指向元素的前面)

返回值是一个迭代器,而不再是 pair 对象。当成功添加元素时,返回的迭代器指向新添加的元素;反之,如果添加失败,则迭代器就指向 set 容器和要添加元素的值相同的元素

删除操作:

size_type erase (const value_type& val)// 返回删除元素的个数

iterator  erase (const_iterator position)// 返回删除元素后容器的第一个元素

set容器没有重载[]运算符,所以无法用下标访问元素;

也没有at()函数,set容器只能通过迭代器访问元素 

补充:multiset(存储元素不必互不相同,即允许值相同) 

queue

queue容器的逻辑结构是队列,物理结构可以是数组或链表

使用前包含头文件#include<queue>

queue类模板定义
template <class T, class _Container = deque<T>>
class queue{
	……
}
T是元素数据类型
Container是底层容器的类型(也就是其物理结构是用数组还是链表,但是不能是vector),缺省为deque

queue容器不支持迭代器 

queue容器常用函数:

构造对象:

queue();  // 创建一个空的队列。

queue(const queue<T>& q);  // 拷贝构造函数。

queue(queue<T>&& q);  // 移动构造函数(C++11标准)

入队出队操作:

void push(const T& value);  // 元素入队。

void emplace(…);           // 元素入队,…用于构造元素。C++11

size_t size() const;          // 返回队列中元素的个数。

bool empty() const;        // 判断队列是否为空。

T &front();                 // 返回队头元素。

T &back();                 // 返回队尾元素。

void pop();                // 出队,删除队头的元素。

比较操作:

queue &operator=(const queue<T> &q);    // 赋值。

void swap(queue<T> &q);    // 交换。

bool operator == (const queue<T> & q) const; // 重载==操作符。

bool operator != (const queue<T> & q) const; // 重载!=操作符。

priority_queue

优先队列,一个有权值的单向队列queue,按优先级进行排序

基本操作与queue相同

deque

deque是双端队列,物理结构是数组,使用前包含头文件#include<deque>

deque容器存储空间多段连续空间,每段连续空间之间不一定连续

deque用一个数组来管理这些连续空间,通过建立数组,分段的连续空间实现整体连续的效果

在两端插入和删除元素的效率高,但在中间插入删除的效率不如vector

随机访问效率不如vector

基本操作与vector相同 

unordered_map&unordered_ multimap

两者的底层都是哈希表

unordered_map与map区别在于逻辑结构,一个是哈希表,一个是红黑树

unordered_map与unordered_multimap区别在于map不允许key重复

unordered_set&unordered_multiset

两者的底层都是哈希表

unordered_set与set区别在于逻辑结构,一个是哈希表,一个是红黑树

unordered_set与unordered_multiset区别在于set不允许value重复

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值