文章目录
Vector容器概述
提示:这里可以添加本文要记录的大概内容:
- 数组array,一旦配置了就不能改变。如果要改变空间大小,就需要重新定义一个数组,将旧数据搬到新空间中,并释放原来的空间。
- vector是一个封装了动态大小数组的顺序容器(单端数组,向量),能够存放各种类型的对象。与普通数组不同,vector可以动态地增长和缩小,以适应程序的需求。
vector具有连续存储的特点,这意味着它的元素在内存中是连续存储的,使得访问元素非常快速。
为了使用vector,需要包含头文件
#include <vector>
v.begin();//获取容器的其实迭代器(指向第0个元素)
v.end();//获取容器的结束迭代器(指向最后一个元素的下一个位置)
front();//头元素
back();//尾元素
Vector 的数据结构
-
Vector所采用的数据结构非常简单,是一种线性连续空间。
-
以两个迭代器Myfirst和Mylast分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器_Myend指向整块连续内存空间的尾端。
为了降低空间配置时的速度成本,vector实际配置的大小可能比声明的大一些,以备扩充需求;即“容量“大于空间,大约2倍
并且vector的动态增加,本质上也是开辟一个更大的内存空间,将原来的数据拷贝到新的内存空间中,并释放原空间(与数组相同)。
Vector API 函数使用
vector创建与访问
vector< T > v;
//采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());
//将v[begin(), end()]区间中的元素拷贝给本身
vector(n, elem);
// 构造函数将n个elem拷贝给本身
vector(const vector& v);
//拷贝构造函数
#include <iostream>
#include <vector>
using namespace std;
void test01()
{
vector<int> v1;//模板类实现,必须指明数据类型
v1.push_back(10);//尾插法,末尾插入10
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
vector<int> v2(5);//预设大小创建
vector<int> v3 = {1,2,3,4,5};//初始化列表创建
vector<int> v4(v1);//拷贝构造
vector<int> v5(v3.begin()+1, v3.end()-1);//范围创建
vector<int> v6(5,1);//复制创建
//遍历容器进行访问
//定义一个迭代器iterator,保存起始迭代器
//迭代器保存的内容相当于数组的下标(元素在数组内的偏移量),所以可以直接用*it取出
vector<int>::iterator it = v1.begin();
for(; it != v1.end(); it++)
{
//*it == int
cout<<*it<<" ";
}
cout<<endl;
//下标访问,类似数组
cout<<"v2(2) = "<<v2[2]<<endl;
cout<<"v3(2) = "<<v3[2]<<endl;
cout<<"v4(2) = "<<v4[2]<<endl;
cout<<"v5(2) = "<<v5[2]<<endl;
//for循环访问
for (int elems : v3) {
cout << elems << " ";
}
cout<<endl;
//安全下标访问
cout << v4.at(3) << endl; // 输出 30
//成员函数访问
cout << "First element: " << v5.front() << endl;// 输出 First element: 2
cout << "Last element: " << v5.back() << endl; // 输出 Last element: 4
cout << *(v5.data() + 2) << endl; // 输出 4
}
void test02()
{
vector<int> v1;
//初始容量和大小都为0
cout<<"容量:"<<v1.capacity()<<endl;
cout<<"大小:"<<v1.size()<<endl;
vector<int>::iterator it;
v1.reserve(1000);//预留空间
int count = 0;
for(int i = 0; i<1000; i++)
{
//插入一个值后,v1.begin()变化,此时赋给it
//如果另辟空间了,那么it与v1.beign()就会不同,再次打印输出
v1.push_back(i);
if(it != v1.begin())
{
count++;
cout<<"第"<<count<<"次开辟空间容量: "<<v1.capacity()<<endl;
it = v1.begin();
}
}
}
int main(int argc, char* argv[])
{
//test01();
//test02();
return 0;
}
- 迭代器访问可以进行范围检查,并且适用于复杂的遍历操作如排序、查找等;
- 下标访问没有边界检查,越界访问可能导致未定义行为,要用[]
- 安全下标访问由于边界检查,其性能略低于下标访问,但是可以防止越界错误,错误时抛出异常;
开辟空间的未雨绸缪机制,下一次开辟的空间会是上一次的两倍;或者预留空间,但是造成浪费
vector的元素修改
- 插入元素:可以使用
vector.push_back()、vector.insert()
等方法在vector末尾或指定位置插入元素。
insert(const_iterator pos, int count, elem); //迭代器指向位置pos插入count个元素ele
insert(v1.begin()+2, 3, 5);
- 删除元素:使用
vector.pop_back()、vector.erase()
等方法可以从vector末尾或指定位置删除元素。
erase(const_iterator start, const_iterator end); //删除区间start到end间的元素
vector<int> v1 = {1,2,3,4,5};
v1.erase(v1.begin(), v1.begin()+2);//3,4,5 位置计数从0开始
erase(const_iterator pos);//删除迭代器指向的元素
clear();//删除容器中所有元素,清楚后大小为0,容量不变
- 修改元素:可以通过下标或迭代器直接修改vector中的元素值。
- 赋值元素:
vector.assign(begin, end);
//将[begin, end)区间中的数据拷贝赋值给本身
vector.assign(n, elem);
//将n个elem拷贝赋值给本身
vector& operatior=(const vector& vec);
//重载等号操作符
vector.swap(vec);
//将vec与本身的元素互换
vector的算法支持
- 查找元素:支持
find()
等STL算法,用于查找特定元素的位置。 - 排序:可以使用
sort()
算法对vector进行排序。 - 合并:可以使用
merge()
等算法合并两个已排序的vector。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template <typename T>
void printVectorAll(const vector<T>& vec)
{
for (const auto& elem : vec) {
cout << elem << " ";
}
cout<<endl;
}
void test()
{
vector<int> v;
v.push_back(10);
v.push_back(30);
v.push_back(20);
v.push_back(50);
printVectorAll(v);
sort(v.begin(), v.end());
printVectorAll(v);
}
int main()
{
test();
}
vector大小操作
vector.size():
这个函数用于返回容器中元素的个数。vector.empty():
这个函数用于判断容器是否为空。如果容器中没有任何元素,那么它就是空的。vector.resize(int num):
这个函数用于重新指定容器的长度为num。如果容器变长,那么新位置将以默认值(0)填充。如果容器变短,那么末尾超出容器长度的元素将被删除。vector.resize(int num, elem):
这个函数也用于重新指定容器的长度为num。与前一个函数不同的是,如果容器变长,新位置将以elem值填充。同样地,如果容器变短,末尾超出容器长度的元素将被删除。vector.capacity():
这个函数用于获取容器的容量。vector.reserve(int len):
这个函数用于预留len个元素长度的空间容量。预留的位置不初始化,元素不可访问。
reszie()只能修改大小,不能修改容量,修改容量可以用swap
#include <iostream>
#include <vector>
using namespace std;
void test()
{
vector<int> v1;
v1.reserve(1000);
v1.push_back(10);
v1.push_back(20);
cout<<"v1容量:"<<v1.capacity()<<endl;
cout<<"v1大小: "<<v1.size()<<endl;
v1.resize(2);
cout<<"v1容量:"<<v1.capacity()<<endl;
cout<<"v1大小: "<<v1.size()<<endl;
vector<int>(v1).swap(v1);//匿名对象,拷贝构造
cout<<"v1容量:"<<v1.capacity()<<endl;
cout<<"v1大小: "<<v1.size()<<endl;
}
int main()
{
test();
}
运行结果:
交换后的匿名对象会被消除,所以原空间就销毁了
vector容器嵌套
#include <iostream>
#include <vector>
using namespace std;
void test()
{
vector<int> v1(5,10);
vector<int> v2(5,20);
vector<int> v3(5,30);
vector< vector<int> > v;//有点类似二维数组
v.push_back(v1);
v.push_back(v2);
v.push_back(v2);
vector< vector<int> >::iterator it = v.begin();
for(; it != v.end(); it++)
{
//*it == vector<int>
vector<int>::iterator it_2 = (*it).begin();//不括号起来会报错
for(; it_2 != (*it).end(); it_2++)
{
cout<<*it_2<<" ";
}
cout<<endl;
}
}
int main()
{
test();
}
Vector自定义类型
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Person
{
friend void printVectorPerson(const vector<Person>& vec);
friend bool comparePerson(Person ob1, Person ob2)
private:
int num;
std::string name;
float score;
public:
Person() {}
Person(int num, std::string name, float score)
{
this->num = num;
this->name = name;
this->score = score;
}
};
void printVectorPerson(const vector<Person>& vec)
{
//常量引用,所以要变成const_iterator
vector<Person>::const_iterator it = vec.begin();
for (; it != vec.end(); it++) {
//*it == Person,无法知道怎么输出
//可以重载*运算符
//(*it).num访问私有变量,要添加为友元函数
cout << (*it).num << " " << (*it).name << " " << (*it).score << endl;
}
}
bool comparePerson(Person ob1, Person ob2)
{
return ob1.num < ob2.num;
}
void test()
{
vector<Person> v1;
v1.push_back(Person(100, "lucy", 77.7f));
v1.push_back(Person(103, "bob", 77.7f));
v1.push_back(Person(101, "tom", 77.7f));
v1.push_back(Person(105, "dema", 77.7f));
v1.push_back(Person(104, "lakes", 77.7f));
printVectorPerson(v1);
//sort(v1.begin(), v1.end());//无法排序,自定义类型的vector需要指定排序规则
sort(v1.begin(), v1.end(), comparPerson);
printVectorPerson(v1);
}
int main()
{
test();
}