Bootstrap

Vector容器


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;
}
  1. 迭代器访问可以进行范围检查,并且适用于复杂的遍历操作如排序、查找等;
  2. 下标访问没有边界检查,越界访问可能导致未定义行为,要用[]
  3. 安全下标访问由于边界检查,其性能略低于下标访问,但是可以防止越界错误,错误时抛出异常;

开辟空间的未雨绸缪机制,下一次开辟的空间会是上一次的两倍;或者预留空间,但是造成浪费


vector的元素修改

  1. 插入元素:可以使用vector.push_back()、vector.insert()等方法在vector末尾或指定位置插入元素。
insert(const_iterator pos, int count, elem); //迭代器指向位置pos插入count个元素ele
insert(v1.begin()+2, 3, 5); 
  1. 删除元素:使用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,容量不变
  1. 修改元素:可以通过下标或迭代器直接修改vector中的元素值。
  2. 赋值元素: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();
}

;