【STL】vector容器如何使用?

前言

上篇博客简述了string类,实际上就是一个用来装字符的容器,后面我会整理其他的容器,首先这篇我介绍的是向量类std::vector,在使用之前需要引入向量库vector。

vector的理解

vector可以看做一个可以按照需要自动增长和缩短的动态数组
内部机理
实际上,vector内部就是用数组存储地址的,我们知道数组是需要在创建的时候指定大小,但是std::vector不需要,这里有一个概念,我们把内部数组能够存放元素的最大数量称为容器容量(capacity),实际元素数量(size)超过容量时,就需要继续申请扩充容量,然而数组无法在末尾直接增加内存的,所以我们需要申请一块更大的连续内存,并把旧内存的数据复制到新内存里面,这个复制操作的时间复杂度很明显就是O(n),随后旧内存被释放。
值得注意的是
扩容时一般会申请适量多的内存
利:以一定内存来换取大幅度提高插入元素时的速度
原因:
当容量大于元素数量时:
插入1个新元素的时间复杂度为O( 1 ),
插入n个新元素的时间复杂度为O(n)。
当容量小于元素数量时:
插入1个新元素的时间复杂度为O( n ),
插入n个新元素的时间复杂度为O(n*n)。
但是还有一种容器既不会浪费内存也可以快速插入就是list

vector的成员类型

由于vector是一个后来人们编写的类,所以具体的内部代码主要由写库的人决定(如扩充容量的多少),不过C++是有标准的(为了达到每个人写的代码可以进行交流),只要按照标准写代码库,这些新声明与定义的类型都可以找到底层类型,例如size_type的底层代码通常是size_t(C++标准中的无符号的整数类型)。
在这里插入图片描述
在使用上,完整的vector类型: std:vecter<存放的元素的类型>
在使用上,完整的成员类型:std:vecter<存放的元素的类型>:上面的成员类型

vector的创建

1.vector<数据类型> v;//<>尖括号是用来指定容器存放的元素的数据类型,也就是说容器只能存放一种数据类型
例:vector<int>v;

2.vectorc数据类型> v(size_type count);//
例:vector<int> v(50);

3.vector<数据类型> v(size_type count,数据的类型value);
例:vector<int> v(10,1);
4.vector<数据类型>v(任意类型的输入迭代器 first,任意类型的输入送代器 last)
例:string str=“woaini”;
.vector<char>v(str.begin(),str.end();

创建时间复杂度

  1. O(1)
  2. O(n)(与 count 成线性)
  3. O(n)(与 count 成线性)
  4. 4.O(n)(与 first 到 last 的距离成线性)

vector的迭代器

时间复杂度:O(1)
1 vector<int>::iterator it=v.begin();
2. vector<int>::const_iterator const it =v.begin();
3. vector<int>::reverse_iterator rbegin();
4. vector<int>::const_reverse_iterator const rbegin();

vector的容量

1 bool flag=v.empty();// 判断容器是否为空O(1)
2.size_type size=size() ; //返回容器中的元素数量O(1),内部实现`

std::distance(begin(),end())//了解更多推荐看候捷的《STL源码剖析》

3.size_type capacity=capacity() ; 获取容器的容量O(1),扩充多少不确定。
4.void reserve(size_type n); 预留容量(与容器的size()成线性)

 vector<int> v;
 v.reserve(1);
 v.phsh_back(1);//直接插入而不需要扩容

**如果 n<=capacity(),则函数没有操作;
如果 n>capacity(),则容器重新分配内存,来扩充容量。
注意:
重新分配内存后,由于内存地址已经发生了改变,这就导致了之前保存下来的这个容器的所有迭代器全部都会失效,不能再使用,如果需要使用迭代器的话,就必须重新通过成员函数begin()和end()获取。
时间复杂度
1-3.O(1);
4.与容器的size()成线性

vector元素访问

时间复杂度都是O(1)
1.中括号[]//获取相应位置的引用
例:v[3]=222;
2.reference at(size_type pos);//同上,但是会判断是否越界
例:v.at(3)=666;
3.reference front(); 获取容器第1个元素的引用
例:cout<<v.front()<<endl;
4.reference back(); 获取容器最后1个元素的引用
例:cout<<v.back()<<endl;
5.int* data(); 获取容器底层数组的首地址
例:int*p=data();
合法范围:[data(),data()+size()]

vector的元素修改

void push_back(const value_type & value);
例:v.push_back(222);
时间复杂度:虽然有可能出现时间复杂度O()的扩容操作,但是由于时间均摊给每一步,时间复杂度还是O(1)
void pop_back();
例:v.pop_back();
注意
1.first和last不能是对象自身的迭代器,否则是未定义行为
2. 如果新的 size()大于旧的 capacity(),则该容器对象所有迭代器和引用都会失效,在插入新元素后,由于原来插入位置的元素及其后面的元素移位,导致原来插入位置及其后面的迭代器和引用全部失效。
iterator insert(iterator pos. const value_type & value);//在pos前一位插入value
void insert(iterator pos. size_type count, const value_type & value);//在pos前插入count个value
void insert(iterator pos.任意类型的输入送代器first任意类型的输入迭代器 last);//插入指定迭代器first到last之间的元素
iterator erase(iterator pos);
例:

string str ="happynewyear"
vector<char> v(str.begin(),str.end());
v.erase(v.begin()+5);

iterator erase(iterator first, iterator last);

v.erase(v.begin()+1,v.begin()+3);//删除2,3, 4

void clear();//清空容器,容器容量不变;
v.clear();
void resize(size_type count);//定义容量
例:v.size(5);
void resize(size_type count, const value_type & value);//定义容量
例:resize(5,666);
如果当前大小大于count,则减少到count个元素如果当前大小小于count
则:
1 后附额外的默认插入的元素
2. 后附额外的 value 的副本时间复杂度O(n),与元素的数量成线性
在这里插入图片描述
◆◆◆◆◆◆◆◆◆◆◆◆◆◆感谢您对这篇文章的阅读,感恩一见三连哦~♡◆◆◆◆◆◆◆◆◆◆◆◆◆◆

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>