顺序容器为开发者提供了控制元素存储和访问顺序的能力,顺序不依赖元素的值,而是元素加入元素容器时的位置相对应
如 list、forward_list 是链式存储结构,而 vector、deque、array、string 为顺序存储结构,在增删改等操作上它们会有不同的特性
容器是 C++对数据结构的一种封装,器本质是面向对象的设计,掌握相关的构造是一件理所当然的事情
默认构造相关的空容器
//example1.cpp
<int> m_list;//默认构造函数构造空容器
list<int> m_vector; vector
将 m_vector 拷贝一份到 m_vector_copy
//example1.cpp
<int> m_vector_copy(m_vector); vector
其范围是[begin,end)范围内的元素
//example1.cpp
<int> m_vector_1(m_vector_copy.begin(), m_vector_copy.end()); vector
//example1.cpp
<int> m_list_1{1, 2, 3};
listfor(auto&item:m_list_1){
<< item << endl;//1 2 3
cout }
迭代器的范围是[begin,end),当容器为空时 begin 等于 end
//example2.cpp
<int> m_list{1, 2, 3};
list<int>::iterator iter = m_list.begin();
listwhile(iter!=m_list.end()){
<< *iter << endl;//1 2 3
cout ++;
iter}
每个容器都定义了多个类型,如 size_type、iterator、const_iterator
//example3.cpp
<int> m_list{1, 2, 3};
list<int>::size_type size = m_list.size();
list<< size << endl;//3 cout
//example3.cpp
<int>::iterator iter = m_list.begin(); list
//example3.cpp
<int>::const_iterator const_iter = m_list.begin();
list//*const_iter = 1;//error readonly
元素引用类型
//example3.cpp
<int>::reference m_list_reference=*(m_list.begin()); // int &m_list_reference;
listm_list_reference = 999;
<< *(m_list.begin()) << endl;//999 cout
const 引用
//example3.cpp
<int>::const_reference m_const_list_reference = *(m_list.begin());//const int &m_const_list_reference
list//m_const_list_reference = 888;
//error:: readonly
for(vector<int>::const_reference item:m_list){//迭代器for循环
<< item << endl;//1 2 3
cout }
容器存储类型的值类型
//example3.cpp
<int>::value_type num = 9;//int num list
容器存储类型的指针类型
//example3.cpp
<int>::pointer ptr;//int *ptr list
容器存储类型 const 指针类型
//example3.cpp
<int>::const_pointer const_ptr;//const int *const_ptr list
迭代器之间的距离
//example3.cpp
<int> vec = {1, 2, 3};
vector<int>::difference_type distance=end(vec) - begin(vec);
vector<< distance << endl;//3 cout
我们以前接触到的 begin 和
end,分别指向第一个元素与最后一个元素的下一个位置,begin 和 end
有多个版本
r 开头的返回反向迭代器,c 开头的返回 const 迭代器
//example4.cpp
<int> vec = {1, 2, 3, 4};
vector<int>::reverse_iterator iter = vec.rbegin();
vectorwhile(iter!=vec.rend()){
<< *iter << endl;//4 3 2 1
cout ++;
iter}
//example4.cpp
<int>::const_iterator const_iter = vec.cbegin();
vector//*const_iter = 999;
甚至还有这样的组合,真实离了个大谱了
//example4.cpp
<int>::const_reverse_iterator const_reverse_iter = vec.crbegin();
vectorwhile (const_reverse_iter!=vec.crend())
{
<< *const_reverse_iter << endl;//4 3 2 1
cout ++;
const_reverse_iter}
主要要掌握容器的构造函数的相关重载,以及赋值拷贝等特性
在前面的构造函数内容中我们已经过实践,可以进行复习与在此学习
是没有这样的转换的,如将 vector<int>转换为 vector<float>,C++中并没有相关的直接操作,但是允许我们使用迭代器范围方式初始化,迭代器相关元素类型必须有相关的构造函数
//example5.cpp
#include<iostream>
#include<vector>
using namespace std;
int main(int argc,char**argv){
<int> vec1{1, 2, 3};
vector//vector<float> vec2(vec1);//没有相关构造函数
<float> vec2(vec1.begin(), vec1.end());//可以用迭代器进行初始化
vectorint num=float(*vec1.begin());//背后可以使用元素类型的构造函数
<< num << endl;//1
cout
//string与char*
const char *str1 = "hello";
const char *str2 = "world";
<const char *> str_vec = {str1, str2};
vector<string> string_vec(str_vec.begin(),str_vec.end());//可以用迭代器进行初始化
vector(*str_vec.begin());//背后可以使用元素类型的构造函数
string str<< str << endl;//hello
cout
return 0;
}
array 具有固定大小
除了 C 风格的数组之外,C++提供了 array 类型,其也是一种顺序容器
//example6.cpp
#include<iostream>
#include<array>
using namespace std;
int main(int argc,char**argv){
//一维array
<int, 10> m_array;
arraym_array[0] = 1;
<< m_array[0] << endl;
cout //二维array
<array<int, 10>, 10> matrix;
array[0][0] = 1;
matrix<< matrix[0][0] << endl;//1
cout
//同理可以具有容器的特性
<array<int, 10>, 10>::size_type size=matrix.size();//size_type
array<array<int, 10>, 10> copy = matrix;//拷贝构造
array<array<int, 10>, 10>::iterator iter = matrix.begin();//迭代器等
array<< (*iter)[0] << endl;//1
cout
return 0;
}
//example7.cpp
<int> vec1 = {1, 2, 3};
vector<int> vec2 = {3, 2, 1};
vector//c1=c2
= vec1;//拷贝
vec2 (vec1,"vec1");//vec1:1 2 3
print_vec(vec2, "vec2");//vec2:1 2 3
print_vec
//c={a,b,c...}通过列表赋值
= {4, 5, 6,7};
vec1 (vec1, "vec1");//vec1:4 5 6 7
print_vec
//swap(c1,c2) 交换两容器的内容
(vec1,vec2);
swap(vec1,"vec1");//vec1:1 2 3
print_vec(vec2, "vec2");//vec2:4 5 6 7
print_vec
//assign操作不适用于关联容器和array
.assign({8,9,10});//列表assign
vec1.assign(vec2.begin(), vec2.end());//迭代器assign
vec1.assign(10, 999);//赋值为10个999 vec1
容器具有成员函数 size,其返回类型为相应容器的 size_type,以及 empty 成员函数
//example8.cpp
<int> vec1 {1, 2, 3};
vector= "123";
string str1 <int>::size_type vec1_size = vec1.size();
vector::size_type str1_size = str1.size();
string<< "vec1_size " << vec1_size << endl;//vec1_size 3
cout << "str1_size " << str1_size << endl;//str1_size 3
cout << str1.empty() << endl;//0
cout << vec1.empty() << endl;//0 cout
容器之间也可以使用<、>、==关系运算符进行比较运算
运算规则与 string 的关系运算类似
1、如果两个容器具有相同大小且所有元素都两两对应相等,则者两个容器相等,否则两个容器不等
2、如果两个容器大小不同,但较小容器中每个元素都等于较大容器中的对应元素,则较小容器小于较大容器
3、如果两个容器都不是另一个容器的前缀子序列,则它们的比较结果取决于第一个不相等的元素的比较结果
//example9.cpp
int arr1[10]{1, 2, 3, 4, 5};
int arr2[10]{1, 2, 3, 4, 5};
<< (arr1 == arr2) << endl;//0
cout //为什么 本质上比较的是头地址哦,忘了的话要去复习数组章节了
//==
<int, 5>array1{1, 2, 3, 4, 5};
array<int, 5>array2{1, 2, 3, 4, 5};
array<< (array1 == array2) << endl;//1
cout
<int> vec1 = {1, 1, 2, 3};
vector<int> vec2 = {
vector1,
1,
3,
1
};
<< (vec1 == vec2) << endl;//0
cout << (vec1 <= vec2) << endl;//1
cout << (vec1 > vec2) << endl;//0 cout
容器的关系运算符依赖于元素的关系运算符,只有容器的元素支持关系运算时,容器整体才可以进行关系运算
主要包括增删改查等操作
向容器内添加元素的有多种方式,不同的容器也有相应的约束以及仅有的特性
在尾部创建一个值为 t 的元素返回 void,除了 array 和 forward_list 之外,每个顺序容器都支持 push_back
//example10.cpp
<int> m_list = {1, 2, 3};
list<int> m_vector = {1, 2, 3};
vectorm_list.push_back(4);
m_list.push_back(4);
//forward_list不支持push_back
在前面添加元素
//example12.cpp
//list forward_list deque容器支持push_front
<int> m_list = {1, 2, 3};
listm_list.push_front(0);
for(auto&item:m_list){
<< item << endl;//0 1 2 3
cout }
在指定位置添加新的元素,vector、deque、list、string 都支持 insert,forward_list 提供了特殊版本的 insert
//example14.cpp
<int> m_list = {1, 2, 3};
listm_list.insert(m_list.begin(), 0);//添加到begin()的前面
m_list.insert(m_list.end(), 4);//添加到end前面
for(auto&item:m_list){
<< item << endl;//0 1 2 3 4
cout }
//example14.cpp
//插入范围内元素
<int> vec1 = {1, 2, 3};
vector<int> vec2 = {};
vector
//insert(iter,num,element)
.insert(vec2.begin(), 3, 0);
vec2for(auto&item:vec2){
<< item << endl;//0 0 0
cout }
//迭代器范围
.insert(vec2.begin(),vec1.begin(),vec1.end());
vec2for(auto&item:vec2){
<< item << endl;//1 2 3 0 0 0
cout }
//列表insert
auto iter=vec2.insert(vec2.begin(), {777, 888, 999});
for(auto&item:vec2){
<< item << endl;//777 888 999 1 2 3 0 0 0
cout }
//新标准中insert返回插入元素中的第一个元素的迭代器
<< *iter << endl;//777 cout
emplace 主要有三种,emplace、emplace_back、emplace_front 分别对应 insert、push_back、push_front,二者的区别是后者直接拷贝到容器内,前者则是将参数传递给元素类型的构造函数
//example15.cpp
class Person{
public:
int age;
;
string name() = default;
Person(int age,string name):age(age),name(name){
Person
}
};
//emplace 与 insert 异曲同工
m_list.emplace(m_list.begin(), 19, "she");
//example13.cpp
m_list.emplace_front(19,"she");
m_list.emplace_front();//使用默认构造函数
//example11.cpp
<Person> m_list;
list//创建临时变量 push_back其拷贝后的副本
m_list.push_back(Person(19,"gaowanlu"));
m_list.emplace_back(19,"she");//传递元素构造参数
适用于 string、vector、deque、array ,下标访问越界时将会抛出 out_of_range 异常
//example16.cpp
= "hello";
string str char &ch = str.at(0);
= 'p';
ch << str << endl;//pello cout
back 不适用于 forward_list ,当容器为空时,函数行为没有定义将会卡住
<int> vec1 = {1, 2, 3, 4};
vectorint &last_el = vec1.back();//最后一个元素的引用
返回第一个元素的引用 ,当容器为空时,函数行为没有定义将会卡住
int &first = vec1.front();
当容器为空时,函数行为没有定义将会卡住
int &num = vec1[0];
= 999;
num << vec1[0] << endl;//999 cout
删除元素会改变容器的大小,标准库提供的删除操作不支持 array
pop_front()为删除首元素,pop_back 为删除尾元素,vector 与 string 不支持 push_front 与 pop_front,forward_list 不支持 pop_back,同时不能对一个空容器操作
//example17.cpp
<int> m_list = {1, 2, 3, 8, 9, 4};
list(m_list);//1 2 3 8 9 4
print_listm_list.pop_front();
(m_list);//2 3 8 9 4
print_listm_list.pop_back();
(m_list);//2 3 8 9 print_list
erase 返回指向删除的元素之后位置的迭代器
//example17.cpp
(m_list);//2 3 8 9
print_listm_list.erase((++m_list.begin()));
(m_list);//2 8 9 print_list
//example17.cpp
(m_list);//2 8 9
print_listauto iter = m_list.begin();
++;
iterm_list.erase(iter,m_list.end());
<< "erase all" << endl;
cout (m_list);//2 print_list
//example17.cpp
//清除全部元素
(m_list);//2
print_listm_list.clear();
(m_list);//nothing
print_list//等价于
m_list.erase(m_list.begin(), m_list.end());
forward_list 就是我们在数据结构中所学习的单向链表,因此就有了对于 forward_list 中插入或者元素删除的特殊操作
//example18.cpp
//获取链表头结点
<int>::iterator head = m_list.before_begin();
forward_listconst auto head1 = m_list.cbefore_begin();
//example18.cpp
m_list.insert_after(head1,0);//值插入
m_list.insert_after(head, 3, 666);//重复值插入
<int> m_list_1 = {6, 7, 8};
forward_listm_list.insert_after(head1,m_list_1.begin(),m_list.end());//迭代器范围插入
m_list.insert_after(head1, {8, 8, 9});//列表插入
m_list.emplace_after(head1, 19.4);//构造函数插入
for(auto&item:m_list){
<< item << " ";
cout //19 8 8 9 6 7 8 666 666 666 0 1 2 3
}
<< endl; cout
同理分为,删除一个指定位置的元素,与迭代器范围内的元素
//example18.cpp
//erase_after
<int> m_list_2={1,2,3,4,5,6};
forward_listm_list_2.erase_after(m_list_2.begin());
for(auto&item:m_list_2){
<< item<<",";//1,3,4,5,6,
cout }
<< endl;
cout //删除(begin,end)之间的元素
m_list_2.erase_after(m_list_2.begin(), m_list_2.end());
for(auto&item:m_list_2){
<< item<<",";//1,
cout }
<< endl; cout
除 array 之外顺序容器可以使用 resize 修改容器的大小,resize 的重载有下面两种形式
如果当前实际大小大于所要求的大小,容器后部的元素会被删除
如果当前实际大小小于新大小,会将新元素添加到容器后部
//example19.cpp
<int> m_vec = {1, 2, 3};
vector(m_vec);//1 2 3
print_vecm_vec.resize(5);//size变大
(m_vec);//1 2 3 0 0
print_vecm_vec.resize(7, 999);//size变大
(m_vec);//1 2 3 0 0 999 999
print_vecm_vec.resize(3);//size变小
(m_vec);//1 2 3 print_vec
向容器添加元素
vector、string
如果存储空间被重新分配,则指向容器的迭代器、指针和引用都失效,如果空间未重新分配,指向插入插入位置之前的迭代器、指针、和引用仍有效,但指向插入位置后的迭代器、指针、引用将失效deque
插入到除首尾位置之外的任何位置将会使迭代器、指针、引用失效,如果在首尾位置插入,迭代器会失效,但引用和指针不会失效list、forward_list
指向容器的迭代器(包括尾后迭代器和首前迭代器)、指针、引用仍有效删除容器中的元素
list、forward_list
指向容器的迭代器(包括尾后迭代器和首前迭代器)、指针、引用仍有效deque
在首尾之外任何位置删除元素,指向被删除元素外其他元素的迭代器、引用、指针失效。删除尾元素,则尾后迭代器
end()失效,但其他迭代器、引用、指针不受影响。删除首元素,这些也不会受影响vector、string
指向被删元素之前元素的迭代器、引用、指针仍有效,当删除元素时,尾后迭代器总会失效学过 insert 返回插入元素的第一个位置的迭代器,erase 返回删除元素之后的元素
//example20.cpp
<int> vec = {0, 1, 2, 3, 4, 5};
vectorauto iter = vec.begin();
while(iter!=vec.end()){
if(*iter%2){//奇数
= vec.insert(iter, *iter);//在iter前插入一个*iter
iter += 2;//将副本和原元素跳过去
iter }else{//偶数
= vec.erase(iter);//返回删除元素的下一个位置的迭代器
iter }
}
for(auto&item:vec){
<< item << " ";//1 1 3 3 5 5
cout }
<< endl; cout
当删除/添加 vector 或 string 中的元素,或者在 deque 中首元素之外位置添加/删除元素,原来的 end 返回的迭代器总会失效,总是在我们保存 end,而是随用随取就好了
//example21.cpp
<int> m_vec = {1, 2, 3, 4};
vectorauto iter = m_vec.begin();
while(iter!=m_vec.end()){//end随用随取
if(*iter%2){//奇数
= m_vec.insert(iter, *iter);
iter += 2;
iter }else{
++;
iter}
}
for(auto&item:m_vec){
<< item << " ";//1 1 2 3 3 4
cout }
<< endl; cout
vector 每次扩展会增添空余的新元素空间,而不是增加一个时只增加一个空间
capacity 返回不扩展内存的情况下,现在最多能容纳多少元素,reserve 操作允许通知容器应该准备多少个存储元素的空间
当 reserve 的需求大小超过 capacity 时才会改变 capacity,分配的大小至少与 reserve 的一样多甚至超过它 ,当 reserve 需求还没有 capacity 大时,增不做操作
对于 shrink_to_fit 只是一个请求,标准库并不保证退还内存
//example22.cpp
<int> m_vec = {1, 2, 3, 4};
vector//capacity
<< m_vec.capacity() << endl;//4
cout m_vec.push_back(5);
m_vec.push_back(6);
<< m_vec.capacity() << endl;//8
cout
//shrink_to_fit
m_vec.shrink_to_fit();
<< m_vec.capacity() << endl;//6
cout
//reserve
m_vec.reserve(100);
<< m_vec.capacity() << endl;//100 cout
只有执行 insert 操作 size 与 capacity 相等,或者调用 resize 或 reserve 时给定的大小超过当前 capacity,vector 才可能重新分配内存空间,分配多少取决于编译器的具体实现
C 字符串与 string 之间的操作
//example23.cpp
const char *c_str = "hello world";
(c_str, 3);
string str1<< str1 << endl;//hel
cout
//string str2(str1, 4);//卡住因为str1中没有4个字符
//cout << str2 << endl;
(c_str, 0, 7);
string str3<< str3 << endl;//hello w
cout //从下标0开始 向后7个字符
用于截取子串
//example24.cpp
= "hello world";
string str1 //s.substr(pos,n)
//从下标4开始后面的字符
<< str1.substr(4) << endl;//o world
cout
//从下标4开始后面的4个字符
<< str1.substr(4, 4) << endl;//o wo
cout
//n过长则到字符串末尾但pos超出范围则会抛出out_of_range异常
<< str1.substr(4, 100) << endl;//o wo
cout
try{
<< str1.substr(100, 9) << endl;
cout }catch(out_of_range error){
<<"ERROR "<< error.what() << endl;
cout //ERROR basic_string::substr: __pos (which is 100) > this->siz() (which is 11)
}
包括 insert、erase、assign 以及 string 特有的 append 与 replace 等操作
下面只是对于 string 特殊的操作,string 同样有顺序容器的接口如 insert 的各种插入形式,需要结合前面的接口进行学习,下面有列举 replace 与 insert 的重载表格可以参考对比
string 的 insert 居然有 7 个重载,怎么记忆?别做梦了,记住怎么可能,有些功能不是只有利用不同的 insert 的才能解决问题,熟记自己喜欢且常用的 insert 进行记忆,在闲暇之余多尝试其他 api,慢慢经验丰富时结合 IDE 的提示,才能发挥好的作用
//example25.cpp
= "hello world";
string str1 const char *c_str = "you";
//在下标2前插入c_str
.insert(2,c_str);//c_str是一个指针哦
str1<< str1 << endl;//heyoullo world
cout
//在下标str1.size()前插入5个感叹号
.insert(str1.size(), 5, '!');
str1<< str1 << endl;//heyoulo world!!!!!
cout
//限制下标范围
= "ABCDEF";
string str2 = "YOU";
string str3 .insert(0,str2,1,2);//str2下标1开始2个字符插入str3下标0前面
str3<< str3 << endl;//BCYOU
cout
//迭代器
= "ABCDEF";
string str4 .insert(str4.begin()++,3,'r');
str4<< str4 << endl;//rrrABCDEF cout
用于删除字符串中的部分片段
//example26.cpp
= "abcdefgh";
string str1
//从下标0开始删除2个字符
.erase(0,2);
str1<< str1 << endl;//cdefgh
cout
//删除从下标3之后的字符
.erase(3);
str1<< str1 << endl;//cde
cout
//使用迭代器 删除某个迭代器位置的字符
.erase(++str1.begin());
str1<< str1 << endl;//ce cout
用于对字符串赋值,string 的 assign 高达 8 个重载,我们自己把握着用 IDE 慢慢研究吧
//example27.cpp
= "abced";
string str1 ;
string str2.assign(str1.c_str(),4);//前4个字符
str2<< str2 << endl;//abce
cout
.assign(str1);
str2<< str2 << endl;//abced
cout
.assign(str1.c_str());
str2<< str2 << endl;//abced cout
append 即在原字符串末尾添加内容,其是 insert 的简写版本,append 有约 6 个重载
//example28.cpp
= "hello";
string str1 .insert(str1.size(),"io");
str1<< str1 << endl;//helloio
cout
= "hello";
str1 .append("io");
str1<< str1 << endl;//helloio cout
其是 erase 与 insert 的简写,即用新的字符串替换原来位置的子字符串,replace 约有 14 个重载
//example29.cpp
= "abcdef";
string str1 //将cd替换为cc
.erase(2,2);
str1.insert(2,"cc");
str1<< str1 << endl;//abccef
cout
= "abcdef";
str1 .replace(2,2,"cc");//从下标2开始替换2个字符
str1<< str1 << endl;//abccef
cout
= "abcdef";
str1 //替换迭代器范围[start,end)内的字符
.replace(str1.begin(),str1.begin()+2,"oo");
str1<< str1 << endl;//oocdef cout
可见其每个方法的重载非常多,要多探究
string 类提供了 6 各不同的搜索函数、每个函数都有 4 个重载
查找 s 中第一次出现的位置,有四种重载
//example30.cpp
= "abcdefg";
string str std::size_t pos=str.find("cdef");
<< pos << endl;//2
cout //没有搜索到返回string::npos
<< (string::npos==str.find("rre")) << endl;//1 cout
查找 s 中 args 最后一次出现的位置,有四种重载
//example30.cpp
//string.rfind
= "abcdefgggg";
str << str.rfind("gg") << endl;//8 cout
在 s 中查找任意一个字符第一次出现的位置,有四种重载
//example30.cpp
//string.find_first_of
= "abcdefhgcb";
str << str.find_first_of("de") << endl;//3 cout
在 s 中查找任意一个字符最后一次出现的位置,有四种重载
//example30.cpp
//string.find_last_of
= "abcdefhgcb";
str << str.find_last_of("gec")<<endl;//8 cout
在 s 中查找第一个不在 args 中的字符,有四种重载
//example30.cpp
//string.find_first_not_of
= "abcdefhgcb";
str << str.find_first_not_of("acde") << endl;//1 cout
在 s 中查找最后一个不再 args 中的字符,有四种重载
//example30.cpp
//string.find_last_not_of
= "abcdefhgcb";
str << str.find_last_not_of("gcfb") << endl;//6 h cout
类似于 C 语言中的 strcmp,同样等于、大于、小于情况分别返回 0、整数、负数
//example31.cpp
= "abcdef";
string str << str.compare("bcde") << endl;//-1
cout << str.compare("aabcd") << endl;//1
cout << str.compare("abcdef") << endl;//0 cout
其重载可以在使用时进行翻阅,用得次数多个自然就记住了
新标准库引入了多个函数,可以实现数值数据与标准库 string 之间的转换
将数字转换为字符串
//example32.cpp
int num1 = 11;
<< to_string(num1)<<endl;
cout unsigned num2 = 22;
<< to_string(num2) << endl;//低于int则会进行提升
cout = to_string(45.66);
string str << str << endl;//45.660000 cout
字符串转 int
//example32.cpp
//stoi
int num3 = stoi("2343", 0, 10);
<< num3 << endl;//2343 cout
字符串转 long
//example32.cpp
//stol
long num4 = stol("-4354", 0, 10);
<< num4 << endl;//-4354 cout
字符串转 unsigned long
//example32.cpp
//stoul
unsigned long num5 = stoul("342");
<< num5 << endl;//342 cout
字符串转 long long
//example32.cpp
//stoll
long long num6 = stoull("48374384");
<< num6 << endl;//48374384 cout
字符串转 unsigned long long
//example32.cpp
//stoull
unsigned long long num7 = stoull("784378");
<< num7 << endl;//784378 cout
字符串转 float
//example32.cpp
//stof
float num8 = stof("43.542");
<< num8 << endl;//43.542 cout
字符串转 double
//example32.cpp
//stod
double num9 = stod("45.232");
<< num9 << endl;//45.232 cout
字符串转 long double
//example32.cpp
//stold
long double num10 = stold("8439.543");
<< num10 << endl;//8439.54 cout
适配器是啥,学过数据结构,例如栈和队列它们都有不同的实现方式,比如顺序栈、链栈,顺序队列、链队列等等,标准库中我们们提供了 stack、queue、priority_queue 适配器,这是一个通用概念
默认情况下,stack 和 queue 是基于 deque 实现的,priority_queue 是在 vector 之上实现的
stack
要求 push_back、pop_back 和 back
操作,因此可以用除了 array、forward_list 之外的任何容器构造queue
要求
back、push_back、front、push_front,可以构造于 list 或 deque
之上,但不能基于 vector 构造priority_queue
除了 front、push_back、pop_back
操作之外还要求随机访问能力,则可以构造于 vector、deque 之上//example33.cpp
<int> deq = {1, 2, 3};
deque//之间使用stack
<int> stk(deq);
stack//在vector上实现空栈
<int, vector<int>> int_stack_base_vector;
stack<string, vector<string>> string_stack_base_vector; stack
//example34.cpp
< int, vector<int>> m_stack({1,2,3});
stack << m_stack.top() << endl;//3
cout m_stack.pop();
m_stack.push(5);//将5压入栈顶
while(!m_stack.empty()){
//栈顶元素
<< m_stack.top() << " ";//5 2 1
cout //弹出栈顶元素
m_stack.pop();
}
priority_queue
允许为队列中的元素建立优先级,新加入的元素会被安排在所有优先级比它低的已有元素之前,默认情况下,标准库在元素类型上使用<
运算符来确定优先级
,也就是谁越大谁优先级就越高,到后面还会详细学习,先不要慌
//example34.cpp
//queue
<int> m_queue({1,2,3});
queuem_queue.push(4);
while(!m_queue.empty()){
<< m_queue.front() <<" ";//1 2 3 4
cout m_queue.pop();
}
<< endl;
cout
//priority_queue
<int> m_priority_queue;
priority_queuem_priority_queue.push(1);
m_priority_queue.push(2);
m_priority_queue.push(3);
m_priority_queue.push(4);
while(!m_priority_queue.empty()){
<< m_priority_queue.top() <<" ";//4 3 2 1
cout m_priority_queue.pop();
}
<< endl; cout