【C++】vector的使用与题目练习
创始人
2024-02-14 01:11:50

文章目录

    • 一、前言
    • 二、构造函数
    • 三、遍历
    • 四、增删查改
        • 1.常用接口
        • 2.增删查改
    • 五、经典题目

一、前言

学习完string类之后,我们在来学习vector难度并没有之前那么高,更加容易理解一些接口

image-20221121155653413

vector是表示可变大小数组的序列容器 ,本质讲,vector使用动态分配数组来存储它的元素。

同理,对于vector的使用,我们也要学会去看文档:vector官方文档

本文重点只介绍一些常用的接口


二、构造函数

构造函数的具体介绍直接前往官网查看文档即可,这里只做简单介绍:

(constructor)构造函数声明接口说明
vector()无参构造
vector(size_type n, const value_type& val = value_type())构造并初始化n个val
vector (const vector& x);拷贝构造
vector (InputIterator first, InputIterator last);使用迭代器进行初始化构造

对于构造函数,这些与string类似,我们就不在多说,直接上手代码:

void Test()
{vector v;//无参构造vector v1(5, 1);//构造并初始5个1vector v2(v1);//拷贝构造vector v3(++v1.begin(), --v1.end());//迭代器初始化构造
}

image-20221124003225580

此外,对于vector和string的关系是无法替代的,string类中有一个接口c_str(),转化成C语言的字符串要以\0结尾,所以string类最后会有一个\0,在操作上+=,<<,>>等。而vector是保存字符的动态数组,不会以\0结尾,不保存\0,且vector是T泛型,所以并不存在谁替代谁。


三、遍历

1.[]

image-20221124170723823

void Test1()
{vector v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);for (size_t i = 0; i < v.size(); i++){//可读可写v[i]++;cout << v[i] << endl;}
}

image-20221124171353930

2.迭代器、范围for()

正向迭代器和反向迭代器

iterator的使用接口说明
begin + end获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置 的iterator/const_iterator
rbegin + rend获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的 reverse_iterator

image-20221124172411500

void Test2()
{vector v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector::iterator it = v.begin();while (it != v.end()){(*it)++;cout << *it << " ";it++;}cout << endl;vector::reverse_iterator rit = v.rbegin();while (rit != v.rend()){(*rit)--;cout << *rit << " ";rit++;}cout << endl;}

image-20221124172834580

迭代器很自然和范围for联系起来:

for (auto e : v)
{cout << e << " ";
}
cout << endl;

四、增删查改

1.常用接口

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize改变vector的size
reserve改变vector放入capacity

resize&&reserve&&扩容问题

前三个比较容易理解,我们就不说了,我们直接来看resize

void Test3()
{vector v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);cout << v.size() << endl;cout << v.capacity() << endl;v.resize(4);cout << v.size() << endl;cout << v.capacity() << endl;
}

image-20221124182133039

对于reserve:

void Test4()
{vector v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);cout << v.size() << endl;cout << v.capacity() << endl;v.reserve(100);cout << v.size() << endl;cout << v.capacity() << endl;v.reserve(50);cout << v.size() << endl;cout << v.capacity() << endl;
}

image-20221124182558930

capacity扩容问题:

capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的

void Test5()
{size_t sz;std::vector foo;sz = foo.capacity();std::cout << "making foo grow:\n";for (int i = 0; i < 100; ++i) {foo.push_back(i);if (sz != foo.capacity()) {sz = foo.capacity();std::cout << "capacity changed: " << sz << '\n';}}
}

VS下:

image-20221124182813678

Linux的g++下:

image-20221124183142374

2.增删查改

vector增删查改接口说明
push_back尾插
pop_back尾删
find查找。(注意这个是算法模块实现,不是vector的成员接口)
insert在position之前插入val
erase删除position位置的数据
swap交换两个vector的数据空间

1.push_back和pop_back的用法比较简单

void Test6()
{vector v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);for (auto e:v){cout << e << " ";}cout << endl;v.pop_back();v.pop_back();for (auto e : v){cout << e << " ";}
}

image-20221124183736146

2.find

注意:算法库中给我们提供一个模板,vector本身并没有find接口,下面我们来看一看:

image-20221124183953276

void Test7()
{vector v;v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);v.push_back(50);vector::iterator pos = find(v.begin(), v.end(), 30);//auto pos = find(v.begin(), v.end(), 30);if (pos != v.end()){cout << "找到了" << endl;}else{cout<<"没找到"<

image-20221124184423943

3.insert和erase

这两个接口通常配合find使用。对于string的insert和erase支持下标,因为string的find刚好可以返回下标位置:

void Test8()
{vector v;v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);v.push_back(50);v.insert(v.begin(), 111);vector::iterator pos = find(v.begin(),v.end(), 30);if (pos != v.end()){v.insert(pos, 70);}for (auto e : v){cout << e << " ";}cout << endl;pos = find(v.begin(), v.end(),70);if (pos != v.end()){v.erase(pos);}for (auto e : v){cout << e << " ";}
}

image-20221124185011651

4.swap

void Test9()
{vector v;v.push_back(1);v.push_back(2);v.push_back(3);vector swapv;swapv.swap(v);cout << "v data:";for (size_t i = 0; i < v.size(); ++i)cout << v[i] << " ";cout << endl;cout << "swapv data:";for (size_t i = 0; i < swapv.size(); ++i)cout << swapv[i] << " ";cout << endl;
}

image-20221124185922917


对于vector的基本使用我们就先说到这里,下面进入我们的题目练习。

五、经典题目

#include 
#include 
using namespace std;
int main(void)
{vectorarray;array.push_back(100);array.push_back(300);array.push_back(300);array.push_back(300);array.push_back(300);array.push_back(500);vector::iterator itor;for (itor = array.begin(); itor != array.end(); itor++){if (*itor == 300){itor = array.erase(itor);}}for (itor = array.begin(); itor != array.end(); itor++){cout << *itor << " ";}return 0;
}

程序首先把100 300 300 300 300 500进行尾插

image-20221124211107332

数据为300时进行删除,同时itor指向下一个元素,但是由于循环回去,for循环末尾itor++会让迭代器指向下一个。

所以只删除了2个值为300的元素,所以答案为100 300 300 500

1.杨辉三角

[118. 杨辉三角](118. 杨辉三角 - 力扣(Leetcode))

此题用C语言做起来非常麻烦,但是用vector来做就变得更简单了:

image-20221124213207500

每行的头和尾都是1,其他的第[j]个=上一行的第[j-1]+[j]

class Solution {
public:vector> generate(int numRows) {vector> vv;vv.resize(numRows);for(size_t i = 0;i

2.电话号码组合

[17. 电话号码的字母组合](17. 电话号码的字母组合 - 力扣(Leetcode))

此题适合采用回溯的做法,可以先定义一个数组进行映射,确定回溯函数参数,确定终止条件,确定单层的逻辑即可解决:

class Solution {private:const string letterMap[10] = {" "," ","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};string s;vector result;void backtracking(const string&digits,int index){if(index == digits.size()){result.push_back(s);return;}int digit = digits[index]-'0';string letter = letterMap[digit];for(int i = 0;i letterCombinations(string digits) {s.clear();result.clear();if(digits.size()==0){return result;}backtracking(digits,0);return result;}
};

3.只出现一次的数ii

137. 只出现一次的数字 II

除某个元素仅出现 一次 外,其余每个元素都恰出现 三次

对于这道题目,我们可以统计所有数字的二进制的各个位之和,每一个元素都出现了 3 次,对应着第 i 个二进制位的 3 个 0或 3 个 1,无论是哪一种情况,出现三次的数字相加起来就是3的倍数,所以最终只需要模3即可:

image-20221124220517500

class Solution {
public:int singleNumber(vector& nums) {int ret = 0;for(int i = 0;i<32;i++){int sum = 0;for(auto& e:nums){sum+=(e>>i)&1;}sum%=3;ret+=(sum<

4.只出现一次的数字 III

260. 只出现一次的数字 III

其中恰好有两个元素只出现一次,其余所有元素均出现两次.

把整个数组异或之后就值剩下那个只出现一次的元素,然后在找出这两个只出现一次元素的不同的二进制位

然后进行分组即可解决此题。

class Solution {
public:vector singleNumber(vector& nums) {vector v;int ret = 0;//整个数组进行异或for(auto e:nums){ret^=e;}//找出不同的二进制位int flag = 0;for(int i = 0;i<32;i++){if((1&(ret>>i)) == 1){flag = i;break;}}//进行分组异或int x1 = 0,x2 = 0;for(auto e: nums){if((1&(e>>flag)) == 1){x1^=e;}else{x2^=e;}}v.push_back(x1);v.push_back(x2);return v;}
};

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...