基本概念
C++ 中的 vector 是一种顺序容器,是一个封装了动态大小数组的顺序容器,可以存放任意类型的数据。vector 可以随着元素的加入自动扩充其大小,并且支持在中间插入或删除元素。
vector 的声明方式为:
vector<元素类型> 数组名;
例如,声明一个储存整数的 vector 变量可以这样写:
vector<int> myVector;
vector 作为一个重要的 C++ STL 容器,在企业开发中有很多应用场景,可以方便地管理和处理大量数据、实现高效算法和数据结构、实现容器适配器和自定义数据结构等。
例如,在企业开发中,经常需要使用一些高效的算法和数据结构来处理特定问题,如排序、图形处理等。vector 提供了快速随机访问元素的优势,可以方便地实现这些算法和数据结构,提高程序效率和质量。
在处理大量数据,如读取文件、处理数据库查询结果集时, vector 可以根据需要自动扩容和释放内存,因此可以灵活地管理内存空间,保证程序运行效率,并且方便对数据进行快速访问。
因此,在学习C++时,熟悉和掌握vector是非常重要的。
主要特点
vector 的主要特点包括:
1. 动态分配内存
vector 内部使用动态分配内存的方式存储元素,可以根据需要自动调整内存空间大小,不需要事先指定容器大小。
2. 随机访问元素
vector 支持通过下标运算符 []
和 at()
函数快速访问元素,复杂度为 O(1),可以用作普通数组一样的数据结构。
3. 在尾部插入和删除元素效率高
由于 vector 内部使用连续的内存存储元素,因此在序列的尾部插入或删除元素效率非常高,复杂度为 O(1)。
4.插入和删除元素效率低
由于 vector 内部采用的是连续的内存存储方式,当需要在序列中间位置插入或删除元素时,需要将该位置之后的元素全部移动,导致效率较低,复杂度为 O(n)。
5. 可以存储任意类型的元素
由于 vector 是一个模板类,因此可以存储任意类型的元素,在实际应用中非常灵活。
常用操作
vector 容器支持添加、访问、删除、插入、替换和清空元素等基本操作:
1.创建 vector 容器:可以通过 vector 类模板来创建一个新的 vector 容器,语法为 std::vector<T> v;
,其中 T 表示存储在 vector 中的元素类型。
std::vector<int> v;
2.添加元素:使用 push_back() 函数可以向 vector 容器的末尾添加一个新元素,语法为 v.push_back(elem);
,其中 elem 表示要添加的元素。
//向 vector 容器中添加元素 5 v.push_back(5);
3.访问元素:vector 容器支持通过下标运算符 []
和 at() 函数访问元素,语法分别为 v[i]
和 v.at(i)
,其中 i 表示要访问的元素下标。
//访问 vector 容器中第三个元素 int elem = v[2];
4.删除元素:使用 erase() 函数可以删除 vector 容器中指定范围内的元素,语法为 v.erase(start, end);
,其中 start 和 end 分别表示要删除元素的起始位置和终止位置。
//删除 vector 容器中第二个到第四个元素 v.erase(v.begin() + 1, v.begin() + 4);
5.获取容器大小:使用 size() 函数可以获取 vector 容器中元素的数量,语法为 v.size();
。
//获取 vector 容器中元素的数量 int size = v.size();
6.判断容器是否为空:使用 empty() 函数可以判断 vector 容器是否为空,语法为 v.empty();
。
bool isEmpty = v.empty();
7.清空容器:使用 clear() 函数可以清空 vector 容器中的所有元素,语法为 v.clear();
。
v.clear();
8.插入元素:使用 insert() 函数可以在 vector 容器中指定位置插入一个新元素,语法为 v.insert(pos, elem);
,其中 pos 表示插入位置的迭代器,elem 表示要插入的元素。
//在 vector 容器中第二个位置插入元素 3 v.insert(v.begin() + 1, 3);
9.替换元素:使用赋值运算符 = 和 assign() 函数可以替换 vector 容器中指定位置的元素,语法分别为 v[i] = elem;
和 v.assign(pos, end, elem);
,其中 i 表示要替换元素的下标,pos 和 end 表示要替换元素的范围,elem 表示替换的新元素。
//将 vector 容器中第四个元素替换为 7 v[3] = 7;
应用实例
给定一个题目:
请实现一个MyQueue类,实现出队,入队,求队列长度:
实现入队函数 void push(int x);
实现出队函数 int pop();
实现求队列长度函数 int size();
输入格式:
每个输入包含1个测试用例。每个测试用例第一行给出一个正整数 n (n <= 10^6) ,接下去n行每行一个数字,表示一种操作:
1 x : 表示从队尾插入x,0<=x<=2^31-1。
2 : 表示队首元素出队。
3 : 表示求队列长度。
输出格式:
对于操作2,若队列为空,则输出 “Invalid”,否则请输出队首元素。 对于操作3,请输出队列长度。
每个输出项最后换行。
可以使用vector容器实现题目求解:
#include <iostream> #include <vector> #include <algorithm> using namespace std; vector<int> obj; //定义一个 vector 对象 obj,用来存储队列元素 int duilie=0,ren=0; //定义两个变量,表示队列的长度和队首元素位置 class MyQueue { //定义 MyQueue 类 private: public: void push(int x) { //定义 push 函数,将元素 x 加入队列 obj.push_back(x); //在 vector 尾部添加元素 duilie++; //队列元素个数加 1 } int pop() { //定义 pop 函数,弹出队首元素并返回该元素值 if(duilie==0) //如果队列为空,弹出无效,输出 "Invalid" cout<<"Invalid"<<endl; if(duilie!=0) //否则,从队列中删除队首元素,并输出该元素值 { cout<<obj[0]<<endl; vector<int>::iterator s = obj.begin(); //定义迭代器 s,将其指向 vector 的起始位置 obj.erase(s); //在 vector 中删除起始位置的元素 duilie--; //队列元素个数减 1 } } int size() { //定义 size 函数,返回队列元素个数(即队列长度) int i; for(i=0;i<obj.size();i++) { ; } cout<<i<<endl; //输出元素个数 i } }; int main(int argc, char *argv[]) { unsigned long long int i,j,k; cin>>i; //输入操作次数 MyQueue a; //创建 MyQueue 对象 a for(j=0;j<i;j++) //进行 i 次操作 { cin>>k; //输入操作类型 switch(k) { case 1: //如果操作类型为 1,再输入要加入队列的元素值 x, //并调用 push 函数将其加入队列 int x; cin>>x; a.push(x); break; case 2: //如果操作类型为 2,调用 pop 函数弹出队首元素 a.pop(); break; case 3: //如果操作类型为 3,调用 size 函数返回队列长度 a.size(); } } }
相较优势
若不适用vector容器,也可使用静态数组解题:
#include<iostream> using namespace std; const int MAXSIZE = 100010; //定义静态数组最大长度 class MyQueue { //定义 MyQueue 类 private: int data[MAXSIZE]; //定义一个静态数组 data,用来存储队列元素 int duilie=0,ren=0; //定义两个变量,表示队列的长度和队首元素位置 public: void push(int x) { //定义 push 函数,将元素 x 加入队列 data[duilie++] = x; //在数组尾部添加元素,并将队列元素个数加 1 } int pop() { //定义 pop 函数,弹出队首元素并返回该元素值 if(duilie==ren) //如果队列为空,弹出无效,输出 "Invalid" cout<<"Invalid"<<endl; else { //否则,弹出队首元素,输出该元素值,并将队列元素个数减 1 cout<<data[ren++]<<endl; } } int size() { //定义 size 函数,返回队列元素个数(即队列长度) cout<<duilie-ren<<endl; //输出队列元素个数 } }; int main(int argc, char *argv[]) { int i,j,k; cin>>i; //输入操作次数 MyQueue a; //创建 MyQueue 对象 a for(j=0;j<i;j++) //进行 i 次操作 { cin>>k; //输入操作类型 switch(k) { case 1: //如果操作类型为 1,再输入要加入队列的元素值 x,并调用 push 函数将其加入队列 int x; cin>>x; a.push(x); break; case 2: //如果操作类型为 2,调用 pop 函数弹出队首元素 a.pop(); break; case 3: //如果操作类型为 3,调用 size 函数返回队列长度 a.size(); } } }
对于上述代码中使用的静态数组和 vector 容器,两者在实现队列数据结构时的具体实现方式是不同的。
在使用静态数组时,需要在定义数组时指定其最大长度,并在操作队列过程中手动维护队列的长度和队首元素位置,如下所示:
class MyQueue { private: int data[MAXSIZE]; int duilie=0,ren=0; public: void push(int x) { data[duilie++] = x; } int pop() { if(duilie==ren) cout<<"Invalid"<<endl; else { cout<<data[ren++]<<endl; } } int size() { cout<<duilie-ren<<endl; } };
在使用 vector 容器时,可以直接使用 vector 的成员函数对元素进行插入和删除,同时 vector 会在需要时自动扩容,并且 vector 容器的 size() 成员函数可以返回容器中元素的个数,如下所示:
class MyQueue { private: vector<int> obj; public: void push(int x) { obj.push_back(x); } int pop() { if(obj.empty()) cout<<"Invalid"<<endl; else { cout<<obj.front()<<endl; obj.erase(obj.begin()); } } int size() { cout<<obj.size()<<endl; } };
因此,相比于静态数组,vector 容器在实现队列数据结构时的操作更加便捷,而且不需要手动维护队列的长度和队首元素位置,使用起来更加便捷。
总结
本文介绍了vector容器的特点
、语法操作
及应用实例
等,vector容器在数据的处理中不可或缺,读者可躬身实践将其掌握。
我是秋说,我们下次见。