首页 > 其他分享 >序列式容器

序列式容器

时间:2024-03-29 23:34:07浏览次数:28  
标签:容器 deque 适配器 元素 list values 序列

STL序列式容器

序列式容器,即以线性排列来存储某一制定类型的数据,该类容器并不会自动对存储元素按照值的大小进行排序。序列式容器大致包括array,vector, deque,list,forward_list等,除此之外,stack和queue本质上也属于序列容器,不过是在deque的基础上形成,故更习惯称他们为容器适配器。

array

​array是C++11标准中新增的序列容器,在普通数组的基础上添加了一些成员函数和全局函数。array容器的大小是固定的,无法动态的扩展或收缩。
初始化array容器:

//array容器以类模板的形式定义在<array>头文件中,位于命名空间std中,使用该容器需要引入<array>头文件,并默认使用std命名空间
#include <array>
using namespace std;

//array<T,N>类模板中,T用以指明容器中的存储的具体数据类型,N用于指明容器的大小,需要注意的是N必须是常量。
//初始化操作
array<double,10> values;//各元素值不确定,不会默认初始化
array<double,10> values{};//容器元素被默认初始化为0
array<double,10> values{1.0,2.0};//剩余八个元素被默认初始化为 0.0

array容器中包含at()这种成员函数,使得操作元素比普通数组更安全。

用法示例:

#include <iostream>
#include <array>
using namespace std;
int main()
{
	std::array<int,4> values{};
    //初始化容器为{0,1,2,3}
    for(int i = 0; i<values.size();i++){
        values.at(i) = i;
    }
    //使用get()重载函数输出指定位置元素
    cout<< get<3>(values)<<endl;
    //cout<<values.at(3)<<endl;
    //如果容器不为空,输出容器内所有元素
    if(!values.empty()){
		for(auto val = values.begin();val<values.end();val++){
            cout<< *val <<" "<<endl;
        }
    }
    //三种访问元素的方式
    cout<< "values[0] is: "<< values[0]<<endl;
    cout<< "values[1] is: "<< values.at(1)<<endl;
    cout<< "values[2] is: "<< get<2>(values)<<endl;
    return 0;
}

访问array容器内单个元素:

容器名[]:没有做边界检查(性能开销),使用越界的索引去访问或者存储元素不会被检测到

容器名.at(索引):可确定索引是否越界

vector

vector 实现的是一个动态数组,即可以进行元素的插入或者删除,动态占用内存空间。在尾部插入或者删除元素时间复杂度为O(1),在容器头部或者中部插入或删除元素时间复杂度为线性阶O(n).vector 容器以类模板vector(T表示存储元素类型)的定义在头文件中,创建vector容器:

#include <iostream>
using namespace std;

//创建空的vector容器
vector<double> values;//空的vector容器
values.reserve(20);//设置容器内存分配,至少容纳20个元素,不影响已存储的元素也不会生成任何元素
//创建时指定初始值和元素个数
vector<int> primes{2,3,4,5};
//创建时指定元素个数,但初始值默认为0
vector<int> primes(20);
//创建时指定元素个数和初始值
vector<double> values(20,1.0);//20个元素的值均为1.0
//复制其他容器元素
vector<int> values1(10,1);
vector<int> values2(values1);
vector<int> values2(values.begin(),values.begin()+2);

vector一些成员函数的用法:

#include <iostream>
#include <vector>
using namespace std;
int main(){
    //初始化一个空的vector 容器
    vector<char> value;
    //向value容器尾部添加s,t,l
    value.push_back('s');
    value.push_back('t');
    value.push_back('l');
    //调用size()成员函数输出容器的元素个数
    printf("元素个数为:%d\n",value.size());
    //使用迭代器遍历容器
    for(auto it = value.begin();it!=value.end();it++){
		cout<<*it<<" ";
    }
    cout << endl;
    //向容器开头插入字符
    value.insert(value.begin(),'r');
    cout<<"首个元素为"<<value.at(0)<<endl;
    return 0;
}
访问元素

1.容器名[索引]:未进行边界检测,可能发生越界访问的错误

容器名.at(索引):会进行边界检测

2.容器名.front():容器第一个元素的引用

容器名.back(): 容器最后一个元素的引用

3.容器名.data():首个元素的指针

添加元素

push_back() 和 emplace_back()

两者底层实现机制不同,push_back()向容器尾部添加元素时,首先会创建这个元素,然后再将元素拷贝或者移动到容器中;而emplace_back()实现时直接在容器尾部创建这个元素,省去拷贝和移动元素的过程。

插入元素

指定位置是指迭代器指定的位置

insert():指定位置之前插入一个或者多个元素

emplace():指定位置之前插入一个元素

删除元素

deque

​ 双端队列容器,deque擅长在序列尾部增加或者删除元素(时间复杂度为O(1),不擅长在序列中间添加或删除元素,该容器可以根据需要修改自身的容量或大小。不同的是deque擅长在序列头部添加或者删除元素,时间复杂度也是O(1),deque容器中存储元素不能保证所有元素都存储在连续的内存空间中。

​ deque以模板类deque(T为存储元素类型)的形式在头文件中,创建deque容器的几种方式

// 创建空的deque容器,创建之后可以做添加或者删除元素的操作
deque<int> d;
// 创建一个具有n个元素的deque,默认为0
deque<int> d(10);
// 建一个具有n个元素的deque且指定初始值
deque<int> d(10,5);
// 可以通过拷贝原有deque容器创建新的deque容器
deque<int> d1(5);
deque<int> d2(d1);

用法示例:

#include <iostream>
#include <deque>
using namespace std;
int main()
{
    //初始化一个空deque容器
    deque<int> q;
    //向d容器尾部依次添加1,2,3
    d.push_back(1);
    d.push_back(2);
    d.push_back(3);
    //向d容器头部直接添加0
    d.push_front(0);
    //调用size函数输出容器存储字符个数
    cout<<"元素个数为"<<d.size()<<endl;
    //使用迭代器遍历容器
    for(auto it = d.begin();it<d.end();it++){
        cout<<*it<<" ";
    }
    cout << endl;
    return 0;
}

​ 向deque容器添加元素时,deque会申请更多的内存空间,同时其包含的所有元素可能会被复制或者移动到新的内存地址,从而导致之前创建的迭代器失效。

​ 访问元素时同样有容器名[索引] 和at的方法,其区别前已说明。同样的front()和back()两个成员函数分别返回容器第一个和最后一个元素的引用。但不存在data()成员函数,因为deque存储元素时并不会将元素存储在连续的内存空间中。

list

​ 双向链表容器,list容器的元素分散存储在内存空间中,而非必须存储在一整块连续的内存空间。各个元素的顺序依靠指针维系,据此可以在序列已知的位置快速插入或者删除元素,但是访问元素需要遍历容器。

​ list容器以模板类list的形式在头文件中,如何创建list容器:

//创建空的list容器
list<int> values;
//创建一个包含n个元素的list容器
list<int> values(10);
//创建包含n个元素的容器并指定初始值
list<int> values(10,3);
//通过拷贝或者指定区域来创建新的容器
list<int> value1(10,4);
list<int> value2(value1);
list<int> value2(value1.begin()+2,value1.end()-1);

list容器的重点在于其迭代器为双向迭代器而不是随机访问迭代器,故不支持通过下标访问list容器内指定位置的元素,仅支持++p,p++,p--,--p,*p,p1==p2以及p1!=P2等运算符。

list在进行插入(insert),接合(splice)等操作时,都不会造成原有的list迭代器失效,甚至删除操作,只有指向被删除元素的迭代器失效。

splice()成员方法移除元素的方式是,将存储该元素的节点从list容器底层的链表中摘除,然后再链接到当前 list容器底层的链表中,这意味着使用splice()成员方法将x容器中的元素添加到当前容器的同时,该元素会从x容器中删除。

删除元素:

根据元素所在位置删除:earse()

根据元素的值删除:remove()

forward_list

单链表,效率高

容器适配器

​ 容器适配器就是将不适用的序列式容器变得适用,通过封装某个序列式容器,并重新组合该容器中包含的成员函数,使其满足某些特定场景的需要。容器适配器的本质上还是容器,只不过此容器模板类的实现,利用了大量其他基础容器模板类中已经写好的成员函数。

​ STL提供三种容器适配器,包括stack栈适配器,queue队列适配器,以及priority_queue优先权队列适配器。

stack

​ stack栈适配器是一种单端开口的容器,该容器实际上模拟的是栈存储结构,stack 适配器的开头端通常称为栈顶,数据的存取只能在栈顶处操作。栈中存储的元素满足后进先出的准则。满足条件的基础容器有vector,deque,list,默认使用的基础容器是deque。

stack容器的创建:以模板类stack<T,Container = deque>(其中T为存储元素的类型,Container表示底层容器的类型)

#include <iostream>
#include <stack>
using namespace std;
//创建不包含元素的stack适配器
stack<int> values;
//定义一个使用list基础容器的stack 适配器
stack<int,list<int>> values;
//使用基础容器初始化
list<int> values{1,2,3};
stack<int,list<int>> my_stack(values);//此时栈顶元素为3,同时stack第二个模板参数必须显式指定为list<int>,和存储类型保持一致,否则使用默认的deque容器将无法用list容器去初始化stack适配器
//用一个stack适配器初始化另一个stack适配器,需要它们存储的元素类型以及底层采用的基础容器类型相同
list<int> values{1,2,3};
stack<int,list<int>> mystack1(values);
stack<int,list<int>> mystack2(mystack1);
//stack<int,list<int>> mysatck2=mystack1;

部分成员函数用法示例

#include <iostream>
#include <stack>
#include <list>
using namespace std;
int main()
{
	//构建stack容器适配器
    list<int> values{1,2,3};
    stack<int,list<int>> mystack(values);
    //查看mystack里面存储元素的个数
    cout<<"size of mystack"<<mystack.size()<<endl;
    //将mystack中存储的元素依次弹栈,直到其为空
    while(!mystack.empty()){
        cout<<mystack.top()<<endl;
        mystack.pop();
    }
    return 0;
}

queue

queue容器适配器有两个开口,一个用来专门输入数据,一个用来专门输出数据。queue成为队列适配器,具有先进先出的特点。

queue容器适配器以模板类queue<T,Container=deque>(其中T为存储元素的类型,Container表示底层容器的类型)的形式位于头文件中

queue的创建

#include<iostream>
#incude<queue>
using namespace std;
//创建空的queue容器适配器
queue<int> values;
//手动指定基础容器的类型,存储的数据类型必须和queue容器适配器存储的元素类型数据一致。queue容器适配器底层容器可以选择deque和list
queue<int,list<int>> values;
//用基础容器初始化queue容器适配器
deque<int> values{1,2,3};
queue<int> myqueue(values);
//用一个queue容器适配器初始化另一个容器适配器
deque<int> values{1,2,3};
queue<int> myqueue1(values);
queue<int> myqueue2(myqueue1);

用法示例

#include <iostream>
#include <queue>
#include <list>
using namespace std;
int main()
{
    //构建 queue 容器适配器
    std::deque<int> values{ 1,2,3 };
    std::queue<int> my_queue(values);//{1,2,3}
    //查看 my_queue 存储元素的个数
    cout << "size of my_queue: " << my_queue.size() << endl;
    //访问 my_queue 中的元素
    while (!my_queue.empty())
    {
        cout << my_queue.front() << endl;
        //访问过的元素出队列
        my_queue.pop();
    }
    return 0;
}

标签:容器,deque,适配器,元素,list,values,序列
From: https://www.cnblogs.com/perngfey-note/p/18104841

相关文章

  • 代码随想录训练营Day31:● 理论基础 ● 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子
    理论基础贪心基础455.分发饼干题目链接https://leetcode.cn/problems/assign-cookies/description/题目描述思路自己写的,因为没有事先对两个数组进行排序,所以出现了问题classSolution{publicintfindContentChildren(int[]g,int[]s){Arrays.s......
  • 本地class序列化用绕过高版本jdk的JNDI题目
    [HZNUCTF2023final]ezjava这道题,困扰许久,不是题目逻辑,而是ldap服务起不了。题目介绍:Trytofxxkit(Log4j打log4j?进网页,开局几个字,提示fastjson:1.2.48:尝试一下常用的log4j2payload打一打DNS测一下:{{urlenc(${jndi:dns://xxxxxxxxx})}}得到回显,可以看到版本为jd......
  • 【力扣】300. 最长递增子序列(DFS+DP两种方法实现)
    目录题目传送最长递增子序列[DFS方法]DFS方法思路图思路简述代码大家可以自行考虑有没有优化的方法最长递增子序列[DP]方法DP方法思路图思路简述代码方案题目传送原题目链接最长递增子序列[DFS方法]DFS方法思路图思路简述对于序列中的每一个数字只有选择......
  • Java Swing容器:文件对话框
           文件对话框是专门用于对文件或目录进行浏览和选择的对话框。可以使用JFileChooser类创建文件对话框,其主要构造方法如下:JFileChooser():根据用户默认目录创建文件对话框。JFileChooser(FilecurrentDirectory):根据File型参数所指定的目录创建文件对话框。JFileCho......
  • R语言用多项式回归和ARIMA模型预测电力负荷时间序列数据
    原文链接:http://tecdat.cn/?p=18037原文出处:拓端数据部落公众号 根据我们对温度的预测,我们可以预测电力消耗。绘制电力消耗序列图: htmlplot(elect,type="l")  我们可以尝试一个非常简单的模型,其中日期Y_t的消耗量是时间,温度(以多项式形式表示)以及工业生产指数IPI......
  • set/ multiset 容器
    set/multiset容器1.1set基本概念简介:所有元素都会在插入时自动被排序本质:set/multiset属于关联式容器,底层结构是用二叉树实现。set和multiset区别:set不允许容器中有重复的元素multiset允许容器中有重复的元素1.2set构造和赋值功能描述:创建set容器以及赋值构......
  • map/ multimap容器
    map/multimap容器1.1map基本概念简介:map中所有元素都是pairpair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)所有元素都会根据元素的键值自动排序本质:map/multimap属于关联式容器,底层结构是用二叉树实现。优点:可以根据key值快速找到value值map和mul......
  • Stack容器
    stack容器1.1stack基本概念概念:stack是一种先进后出(FirstInLastOut,FILO)的数据结构,它只有一个出口栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为栈中进入数据称为---入栈push栈中弹出数据称为---出栈pop1.2stack常用接口功能描述:栈容器常......
  • Queue 容器
    queue容器1.1queue基本概念概念:Queue是一种先进先出(FirstInFirstOut,FIFO)的数据结构,它有两个出口队列容器允许从一端新增元素,从另一端移除元素队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为队列中进数据称为---入队push队列中出数据称为---......
  • Vector容器
    vector容器最常用的容器之一1.1vector基本概念功能:vector数据结构和数组非常相似,也称为单端数组vector与普通数组区别:不同之处在于数组是静态空间,而vector可以动态扩展动态扩展:并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间......