欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

C++STL序列式容器

时间:2023-04-28

序列式容器,即以线性排列(类似普通数组的存储方式)来存储某一指定类型(例如 int、double 等)的数据,需要特殊说明的是,该类容器并不会自动对存储的元素按照值的大小进行排序。序列式容器有array, vector, deque, list, forward_list。

array,静态数组容器,此类容器一旦建立,其长度就固定不变,即不能增加或删除元素,而只能改变某个元素的值;可直接访问某一元素

vector,向量容器,是一个长度可变的容器,即存储空间不足时会自动申请更多内存,在尾部增加或删除元素的效率最高(时间复杂度为 O(1) 常数阶),在其它位置插入或删除元素效率较差(时间复杂度为 O(n) 线性阶,其中 n 为容器中元素的个数);可直接访问某一元素

deque,双端队列容器,与vector相似,区别在于使用该容器不仅尾部插入和删除高效,在头部插入和删除元素也同样高效,时间复杂度都是 O(1) 常数阶,但是在容器中某一位置处插入或删除元素,时间复杂度为 O(n) 线性阶;可直接访问某一元素

list,双向链表容器,是一个长度可变的以双向链表的形式组织元素的容器,在这个序列的任何地方都可以高效地增加或删除元素(时间复杂度都为常数阶 O(1)),但访问容器中任意元素的速度要比前三种容器慢,这是因为 list 必须从第一个元素或最后一个元素开始访问,需要沿着链表移动,直到到达想要的元素

forward_list,单向链表容器,和list容器相似,只不过它以单链表的形式组织元素,它内部的元素只能从第一个元素开始访问,是一类比链表容器快、更节省内存的容器

序列式容器 array

array 容器是在 C++ 普通数组的基础上,添加了一些成员函数和全局函数。在使用上,它比普通数组更安全,且效率并没有因此变差。array 容器的大小是固定的,无法动态的扩展或收缩,这也就意味着,在使用该容器的过程无法借由增加或移除元素而改变其大小,它只允许访问或者替换存储的元素。

array 容器以类模板的形式定义在 头文件,并位于命名空间 std 中。

#include using namespace std;//构造array a;//定义具有9个int型元素的array容器array a{};//定义具有9个int型元素的array容器并初始化array a{1,2,3};//定义具有9个int型元素的array容器,并指定前三个元素,其余元素初始化为0array a = {1,2,3};//同上array a1(a);//复制构造array a1 = a;//同上array , 9> aa{};//定义二维数组并初始化各元素为0

//迭代器a.begin(); //返回迭代器, 指向第一元素a.end(); //返回迭代器, 指向最末元素的下一个位置a.cbegin(); //返回迭代器, 指向第一元素, 类型为consta.cend();//返回迭代器, 指向最末元素的下一个位置,类型为consta.rbegin(); //返回反向迭代器, 指向反向迭代的第一元素a.rend(); //返回反向迭代器, 指向反向迭代的最末元素的下一个位置a.crbegin(); //返回反向迭代器, 指向反向迭代的第一元素, 类型为consta.crend(); //返回反向迭代器, 指向反向迭代的最末元素的下一个位置, 类型为const//批量赋值a.assign(3);//将容器的每个元素都赋值成 3a.fill(4);//将容器的每个元素都赋值成 4//交换a.swap(a1);//交换两个容器的内容//例:a={1,2,3,4}, a1={5,6,7}//运行之后, a={5,6,7}, a1={1,2,3,4} //访问a[1];//返回下标为 id 的元素, 不检查是否越界a.at(1);//返回下标为 id 的元素, 如果越界抛出异常a.front();//返回首位元素a.back();//返回末位元素//容量a.empty();//容器为空返回true, 否则返回 false;即size=0时为truea.size();//返回容器内目前的元素个数, array定义之后不变a.max_size();//返回元素个数 size 的最大值;返回的值和a.size()相同.//注: 由于array 是静态数组, 因此这里的 size 和 max_size 相同

//遍历array, 5> a{};//假定a是二维数组,且维度为[5,4]for(auto & it1 : a)// it1是array类型的引用{ for(int & it2 : it1)//it2是int类型的引用 { cout << it2 << " "; } cout << endl;}

序列式容器 vector

vector 容器是 STL中最常用的容器之一,它和 array 容器非常类似,都可以看做是对 C++普通数组的“升级版”。不同之处在于,array 实现的是静态数组(容量固定的数组),而 vector 实现的是一个动态数组,即可以进行元素的插入和删除,在此过程中,vector 会动态调整所占用的内存空间,整个过程无需人工干预。

vector 常被称为向量容器,因为该容器擅长在尾部插入或删除元素,在常量时间内就可以完成,时间复杂度为O(1);而对于在容器头部或者中部插入或删除元素,则花费时间要长一些(移动元素需要耗费时间),时间复杂度为线性阶O(n)。

vector的size和capacity,size是当前vector容器真实占用的大小(即容器内存储着多少数据),capacity是预分配的内存空间大小;分别对应resize()和reserve()方法,前者改变容器真实占用大小,后者改变预分配的内存空间大小。

#includeusing namespace std;//一些初始化方式vector a;//定义空的vector容器avector a(10);//定义包含10个元素的容器a并默认初始化各个元素为0vector a(10, 1);//定义包含10个元素的容器a并初始化各个元素为1vector a{1,2,3,4};//定义容器a并初始化它vector a = {1,2,3,4};//同上vector a(b);//从同容器中复制构造vector a(b.begin(), b.begin()+3);//从其他容器中构造int b[7] = {1, 2, 3, 4, 5, 6, 7};vector a(b, b+7);//从数组中构造vector> v(4, vector(5));//静态构造二维数组,维度为[4,5]

//迭代器vec.begin();//得到vector头的指针vec.end();//得到vector的最后一个单元+1的指针vec.rbegin();//将vector反转后的开始指针返回(其实就是原来的end-1)vec.rend();//将vector反转构的结束指针返回(其实就是原来的begin-1)vec.cbegin();vec.cend();vec.crbegin();vec.crend();//容量vec.size();//当前使用数据的大小vec.max_size();//得到vector最大可以是多大/ 区别于vec.size()vec.capacity();//当前vector分配的大小vec.empty();//判断vector是否为空,空时返回true,即size为0时返回truevec.resize();//改变当前使用数据的大小,如果它比当前使用的大,则填充默认值vec.reserve();//改变当前vector所分配空间的大小vec.shrink_to_fit();//将内存减少到等于当前元素实际使用的大小//访问vec[1];//得到1号位置的数据vec.at(1);//得到1号位置的数据vec.front();//返回首位元素的引用vec.back();//返回末位元素的引用vec.data();//返回指向容器中第一个元素的指针//修改vec.assign(n, ele);//将vec赋值为n个ele元素vec.assign(first, last);//将vec赋值为[first,last)之间的元素vec.push_back();//在最后位置添加一个数据vec.insert(it, ele);//在迭代器it指定的位置之前插入元素elevec.insert(it, n, ele);//在迭代器it指定的位置之前插入n个元素elevec.insert(it, first, last);//在迭代器it指定的位置之前,插入其他容器(不仅限于vector)中位于 [first,last) 区域的所有元素vec.insert(it, {12, 34});//在迭代器 pos 指定的位置之前,插入初始化列表(用大括号{}括起来的多个元素,中间有逗号隔开)中所有的元素vec.emplace(it, ele);//在迭代器it指定的位置之前插入元素elevec.emplace_back();//在末尾生成一个元素vec.pop_back();//去掉最后一个数据vec.erase(it);//删除迭代器it指向的元素vec.erase(beg, end);//删除 vector 容器中位于迭代器 [beg,end)指定区域内的所有元素vec.clear();//删除 vector 容器中所有的元素vec.swap(vec1);//来自于algorithm的函数,与另一个vector容器vec1交换数据remove(vec.begin(), vec.end(), ele);//来自于algorithm的函数,可删除容器中所有和指定元素值相等的元素,注意删除后容器大小不变,容量也不变

序列式容器 deque

deque是一个double-ended queue,又称双端队列容器。deque在序列尾部和头部添加和删除元素的时间复杂度是O(1)(vector容器只擅长在序列尾部添加和删除元素),在中间添加和删除元素的时间复杂度要更高。deque也是一个动态容器,可以根据需要修改自身容量和大小。与vector容器不同,deque 容器中存储元素并不能保证所有元素都存储到连续的内存空间中。

#include using namespace std;deque d;//创建一个空dequedeque d(nSize);//创建一个deque,元素个数为nSize,且各个元素初始化为默认值deque d(nSize, t);//创建一个deque,元素个数为nSize,且值均为tdeque d{1,2,3,4,5};//创建并初始化一个dequedeque d = {1,2,3,4,5};//同上//也可从数组中构造,从其他容器中构造,或者复制构造

用法参考 vector 容器,

和 vector 相比,额外增加了实现在容器头部添加和删除元素的成员函数,同时删除了 capacity()、reserve() 和 data() 成员函数。

//迭代器//容量d.size();d.max_size();d.resize(n);//将deque的长度改为n,超出的元素将被删除d.empty();//deque为空返回true,否则返回falsed.shrink_to_fit();//将内存减少到等于当前元素实际所使用的大小//访问d.at(1);d[1];d.front();//获取deque头部元素的引用d.back();//获取deque最后一个元素的引用//修改d.assign();d.push_back();d.push_front();d.emplace_back();d.emplace_front();d.insert();d.emplace();d.pop_back();d.pop_front();d.erase();d.clear();

序列式容器 list

STL list 容器,又称双向链表容器,即该容器的底层是以双向链表的形式实现的。这意味着,list 容器中的元素可以分散存储在内存空间里,而不是必须存储在一整块连续的内存空间中。

list 容器中各个元素的前后顺序是靠指针来维系的,每个元素都配备了 2 个指针,分别指向它的前一个元素和后一个元素。其中第一个元素的前向指针总为 null,因为它前面没有元素;同样,尾部元素的后向指针也总为 null。

基于这样的存储结构,list 容器具有一些其它容器(array、vector 和 deque)所不具备的优势,即它可以在序列已知的任何位置快速插入或删除元素(时间复杂度为O(1))。并且在 list 容器中移动元素,也比其它容器的效率高。使用 list 容器的缺点是,它不能像 array 和 vector 那样,通过位置直接访问元素。

list 容器在头文件中,并位于 std 命名空间中。

#include using namespace std;list l;//声明一个空列表;list l(n);//声明一个有n个元素的列表,每个元素都是由其默认构造函数T()构造出来的list l(n,val);//声明一个由n个元素的列表,每个元素的值都是val得来的 list l{1,2,3};//声明并初始化一个列表//也可以从数组中构造,从其他容器中构造,或者复制构造

序列式容器 forward_list

forward_list 是 C++ 11 新添加的一类容器,其底层实现和 list 容器一样,采用的也是链表结构,只不过 forward_list 使用的是单链表,而 list 使用的是双向链表。

forward_list 容器具有和 list 容器相同的特性,即擅长在序列的任何位置进行插入元素或删除元素的操作,但对于访问存储的元素,没有其它容器(如 array、vector)的效率高。另外,由于单链表没有双向链表那样灵活,因此相比 list 容器,forward_list 容器的功能受到了很多限制。比如,由于单链表只能从前向后遍历,而不支持反向遍历,因此 forward_list 容器只提供前向迭代器,而不是双向迭代器。这意味着,forward_list 容器不具有 rbegin()、rend() 之类的成员函数。

forward_list 容器底层使用单链表,存储相同个数的同类型元素,单链表耗用的内存空间更少,空间利用率更高,并且对于实现某些操作单链表的执行效率也更高。

forward_list 容器包含在头文件中,并定义在 std 命名空间中。

#include using namespace std;forward_list fl;//创建一个没有任何元素的空 forward_list 容器forward_list fl(n);//创建一个包含 n 个元素的 forward_list 容器,并且各个元素被默认初始化forward_list fl(n, value);//创建一个包含 n 个元素的 forward_list 容器,并为每个元素指定初始值forward_list fl{1,2,3};//创建并初始化forward_list fl = {1,2,3};//同上//从数组中构造,从其他容器中构造,或者复制构造

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。