vector使用以及模拟实现

vector使用以及模拟实现

    • vector介绍
    • vector常用接口
      • 1.构造
      • 2.迭代器
      • 3.容量
      • 4.增删查改
      • 5.练习
    • vector模拟实现
      • 1.迭代器失效
      • 2.反向迭代器
      • 3.完整代码

vector介绍

  1. 和我们原来讲的string不同,vector并不是类,是一个类模板,加<类型>实例化以后才是类。
  2. vector是表示可变大小数组的序列容器。
  3. 像数组一样,vector也采用的连续存储空间来存储元素,但是容量可以动态改变。
  4. 和其它容器相比,vector访问元素、尾插、尾删较高效,但不在尾部的插入和删除效率比较低,需要频繁插入和删除的话不建议使用vector



vector常用接口

1.构造

函数声明功能
vector()(常用)无参构造
vector
(size_type n, const value_type& val = value_type())
构造并初始化n个val
vector (const vector& x)(常用)拷贝构造
vector (InputIterator first, InputIterator last)迭代器区间初始化
(模板,可以传入其它容器的迭代器区间)

2.迭代器

函数声明功能
begin()加end() (常用)获取第一个数据位置的iterator/const_iterator,获取最后一个数据的下一个位置的iterator/const_iterator
rbegin()加rend()反向迭代器,获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator

3.容量

函数声明功能
size() (常用)获取数据个数
capacity()获取容器容量
empty()判断是否为空(size为0为空,返回true)
resize(size_type n, value_type val = value_type())     1.n>size()时从尾开始填充val直到容器满;
2.n>容量就先扩容再填充;
     3.n<size()时缩小size(),保留前n个。
reserve(size_t n = 0)预留空间,n大于容量时扩容,不然什么都不做

4.增删查改

函数声明功能
push_back (const value_type& val)(常用)尾插
pop_back()(常用)尾删
find (InputIterator first, InputIterator last, const T& val)不是vector接口,是算法库里面的模板,传入一段迭代器区间,可以在该区间查找val
insert (iterator position, const value_type& val)在position前插入val
erase (iterator position)删除position位置的数据
swap (vector& x)交换两个vector的数据空间
operator[] (size_type n)像数组一样访问数据

5.练习

  • 只出现一次的数字i

题目要求:
在这里插入图片描述

题解:

class Solution 
{
public:int singleNumber(vector<int>& nums) {//这个题需要异或这个位运算//异或是相同为0,不同为1。//所以两个相同的数异或会得到0//0和任何数异或都得到这个数本身//题目明确了只有一个数出现一次,其它都出现两次//因此我们可以把所有数异或一次,出现两次的数字会抵消变成0//最后出现一次的数字一定可以留下来int end = 0;vector<int>::iterator it = nums.begin();//auto it = nums.begin();while(it != nums.end()){end ^= *it;it++;}//范围for同理// for(auto ch : nums)//     end ^= ch;return end;}
};


  • 删除排序数组中的重复项

题目要求:
在这里插入图片描述


题解:
在这里插入图片描述

class Solution {
public:int removeDuplicates(vector<int>& nums) {int sum = 1;int slow = 1;int fast = 1;//快慢指针while(fast < nums.size()){if(nums[fast] > nums[fast-1]){nums[slow++] = nums[fast++];sum++;}else{fast++;}}return sum;        }
};


  • 杨辉三角

题目要求:
在这里插入图片描述

题解:
在这里插入图片描述

class Solution {
public:vector<vector<int>> generate(int numRows) {vector<vector<int>> vv;//把size调整为numRowsvv.resize(numRows);for(int i = 0; i < numRows; i++){vv[i].resize(i+1,0);//每一行最后一个和第一个初始为1vv[i][0] = vv[i][vv[i].size()-1] = 1;}for(int i = 0; i < numRows; i++){for(int j = 0; j < vv[i].size(); j++){if(vv[i][j] == 0)                vv[i][j] = vv[i-1][j] + vv[i-1][j-1];                }}return vv;}
};



vector模拟实现

1.迭代器失效

      迭代器的主要作用就是让算法能够不用关心底层数据结构,而vector迭代器的底层实际是一个指针,在对容器进行操作(例如插入、删除、修改等)后,之前获取的迭代器可能会变得无效


可能会导致其迭代器失效的操作有:
  1. 会引起其底层空间改变的操作(扩容),都有可能是迭代器失效,比如:resize、reserve、insert、push_back等。
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
#include <vector>
int main()
{vector<int> v{ 1,2,3,4,5,6 };auto it = v.begin();// 将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容// v.resize(100, 8);// reserve的作用就是改变扩容大小但不改变有效元素个数,操作期间可能会引起底层容量改变// v.reserve(100);// 插入元素期间,可能会引起扩容,而导致原空间被释放// v.insert(v.begin(), 0);// v.push_back(8);// 给vector重新赋值,可能会引起底层容量改变v.assign(100, 8);/*出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层旧空间被释放掉,而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃。解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给it重新赋值即可。*/while (it != v.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

  1. 指定位置元素的删除操作–erase

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
#include <vector>
int main()
{vector<int> v{ 1,2,3,4,5,6 };//earse不会影响底层的空间(不进行扩容和缩容)//但是也存在迭代器失效的问题//下面这段代码用来删除v中的偶数auto it = v.begin();while (it != v.end()){if (*it % 2 == 0) {//把这个位置数据删除掉v.erase(it);}it++;}//结果:程序崩溃//原因:看图解,erase是会改变end()的//解决方法:每次erase操作后都及时更新迭代器//erase会返回被删除数据下一位置的迭代器//auto it = v.begin();//while (it != v.end())//{//	if (*it % 2 == 0)//	{//		//把这个位置数据删除掉//		it = v.erase(it);//	}//	else//	{//		it++;//	}//}return 0;
}

2.反向迭代器

      vector的反向迭代器实现并不困难,只需要复用普通的迭代器,++操作变成调用普通迭代器的–,–调用++即可。

// 反向迭代器需要进行封装,其实就是复用普通迭代器,然后++和--操作反过来
//这里设计模板参数除了迭代器,还有Ref(引用)和Ptr(指针)
//这样设计是为了同时生成普通迭代器和const对象的迭代器//普通对象(可读可写):Reverse_iterator<iterator,T&,T*>
//const对象(可读不可写):Reverse_iterator<const_iterator,const T&,const T*>
template<class Iterator, class Ref, class Ptr>
struct Reverse_iterator
{//给自己也重命名一下,方便用typedef Reverse_iterator<Iterator, Ref, Ptr> self;Iterator _it;Reverse_iterator(Iterator it):_it(it){}self& operator++(){_it--;return *this;}self operator++(int){self tmp(*this);_it--;return tmp;}self& operator--(){_it++;return *this;}self operator--(int){self tmp(*this);_it++;return tmp;}Ref operator*(){return *_it;}//返回指针可以让自定义类型自行打印,访问成员//->操作符,比较特殊,it->_num转换出来其实是it.operator->()->_numPtr operator->(){return _it;}bool operator!=(const self& s){return _it != s._it;}bool operator==(const self& s){return _it == s._it;}
};

3.完整代码

采用三个迭代器(指针)来维护底层空间:

private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;

在这里插入图片描述


#pragma once
#include<iostream>
#include<assert.h>
//#include<vector>
using namespace std;//和库里面的区分开
namespace MyVector
{// 反向迭代器需要进行封装,其实就是复用普通迭代器,然后++和--操作反过来//这里设计模板参数除了迭代器,还有Ref(引用)和Ptr(指针)//这样设计是为了同时生成普通迭代器和const对象的迭代器//普通对象(可读可写):Reverse_iterator<iterator,T&,T*>//const对象(可读不可写):Reverse_iterator<const_iterator,const T&,const T*>template<class Iterator, class Ref, class Ptr>struct Reverse_iterator{//给自己也重命名一下,方便用typedef Reverse_iterator<Iterator, Ref, Ptr> self;Iterator _it;Reverse_iterator(Iterator it):_it(it){}self& operator++(){_it--;return *this;}self operator++(int){self tmp(*this);_it--;return tmp;}self& operator--(){_it++;return *this;}self operator--(int){self tmp(*this);_it++;return tmp;}Ref operator*(){return *_it;}//返回指针可以让自定义类型自行打印,访问成员//->操作符,比较特殊,it->_num转换出来其实是it.operator->()->_numPtr operator->(){return _it;}bool operator!=(const self& s){return _it != s._it;}bool operator==(const self& s){return _it == s._it;}};//vector类模板template <typename T>class vector{public:typedef T* iterator;typedef const T* const_iterator;typedef Reverse_iterator<iterator, T&, T*> reverse_iterator;typedef Reverse_iterator< const_iterator, const T&,const T*> reverse_const_iterator;iterator begin(){//隐式类型转换return _start;}iterator end(){return _finish;}const_iterator begin()const{return _start;}const_iterator end()const{return _finish;}reverse_iterator rbegin(){return  _finish-1;}reverse_iterator rend(){return _start-1;}reverse_const_iterator rbegin()const{return _finish-1;}reverse_const_iterator rend()const{return _start-1;}/////无参构造vector(){}//函数模板,传入容器的一段迭代器区间template <typename InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);first++;}}//构造vector(const vector<T>& v){//提前开好空间reverse(v.capacity());for (auto& e : v){push_back(e);}}vector(size_t n, const T& val = T()){reverse(n);for (size_t i = 0; i < n; i++){push_back(val);}}//重载给内置类型使用//没有的话vector<int> v(5,0)会优先和vector(InputIterator first, InputIterator last)匹配//对整形解引用会报错vector(int n, const T& val = T()){reverse(n);for (int i = 0; i < n; i++){push_back(val);}}~vector(){delete[] _start;_start = _finish = _endofstorage = nullptr;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);}//传值传参,拷贝一份,直接交换操作的空间即可vector<T>& operator=(vector<T> v){swap(v);return *this;}/// ///void reverse(size_t n){if (n > capacity()){//这里扩容空间会变化,先记录size//这里扩容空间会变化,先记录size//这里扩容空间会变化,先记录sizesize_t sz = size();T* tmp = new T[n];//这里涉及到深浅拷贝for (size_t i = 0; i < sz; i++){tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = _start + sz;_endofstorage = _start + n;}}void resize(size_t n, const T& val = T()){if (n <= size()){_finish = _start + n;}else{//先扩容reverse(n);while (_finish < _start + n){*_finish = val;_finish++;}}}T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos)const{assert(pos < size());return _start[pos];}size_t capacity()const{return _endofstorage - _start;}size_t size()const{return _finish - _start;}/// ///void push_back(const T& x){//复用即可insert(end(), x);}void insert(iterator pos, const T& x){assert(pos <= _finish && pos >= _start);if (_finish == _endofstorage){size_t gap = pos - _start;//初始扩容需要指定给reverse(capacity() == 0 ? 4 : 2 * capacity());pos = _start + gap;}iterator end = _finish;while (end > pos){*end = *(end - 1);end--;}*pos = x;_finish++;			}iterator erase(iterator pos){assert(pos < _finish&& pos >= _start);iterator it = pos + 1;while (it < _finish){*(it - 1) = *it;it++;}_finish--;return pos;}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;};}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/41126.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

主机防护的重要性和方式

01 主机防护的重要性 主机防护是网络安全的重要组成部分。在互联网时代&#xff0c;网络攻击成为了一种常见的威胁&#xff0c;而主机防护则是保护计算机系统免受网络攻击的重要手段。 主机防护可以防范各种网络攻击&#xff0c;如病毒、木马、黑客攻击等&#xff0c;从而保…

气象监测站:用科技感知气象变化

气象监测站是利用科学技术感知当地小气候变化情况的气象观测仪器&#xff0c;可用于农业、林业、养殖业、畜牧业、环境保护、工业等多个领域&#xff0c;提高对环境数据的利用率&#xff0c;促进产业效能不断提升。 气象监测站主要由气象传感器、数据传输系统、电源系统、支架…

Linux debian12解压和压缩.rar文件教程

一、Debian12安装rar命令 sudo apt install rar二、使用rar软件 1.解压文件 命令格式&#xff1a; rar x 文件名.rar实力测试&#xff1a; [rootdoudou tmp]# rar x test.rar2.压缩文件 test是一个文件夹 命令格式&#xff1a; rar a 文件名.rar 文件夹名实例测试&#x…

centos7 yum获取软件所有依赖包 创建本地yum源 yum离线安装软件

centos7 yum获取软件所有依赖包 创建本地yum源 离线安装软件 1、以安装docker 20.10为例2、centos7 yum获取docker 20.10 所有依赖包3、创建本地docker yum源4、yum使用本地docker源 离线安装docker 1、以安装docker 20.10为例 参考链接&#xff1a; 添加docker 清华软件源 y…

git环境超详细配置说明

一&#xff0c;简介 在git工具安装完成之后&#xff0c;需要设置一下常用的配置&#xff0c;如邮箱&#xff0c;缩写&#xff0c;以及git commit模板等等。本文就来详细介绍些各个配置如何操作&#xff0c;供参考。 二&#xff0c;配置步骤 2.1 查看当前git的配置 git conf…

使用 Apache Kafka 和 Go 将数据引入 OpenSearch

需要编写自定义集成层来满足数据管道中的特定要求&#xff1f;了解如何使用 Go 通过 Kafka 和 OpenSearch 实现此目的。 可扩展的数据摄取是OpenSearch等大规模分布式搜索和分析引擎的一个关键方面。构建实时数据摄取管道的方法之一是使用Apache Kafka。它是一个开源事件流平台…

米尔瑞萨RZ/G2L开发板-02 ffmpeg的使用和RTMP直播

最近不知道是不是熬夜太多&#xff0c;然后记忆力减退了&#xff1f; 因为板子回来以后我就迫不及待的试了一下板子&#xff0c;然后发现板子有SSH&#xff0c;但是并没有ffmpeg&#xff0c;最近总是在玩&#xff0c;然后今天说是把板子还原一下哇&#xff0c;然后把官方的固件…

前端单点登录SSO面试回答

JWT鉴权机制 1.JWT用于登录身份验证 2.用户登录成功后&#xff0c;后端通过JWT机制生成一个token&#xff0c;返回给客户端 3.客户端后续的每次请求都需要携带token&#xff0c;放在header的authorization中 4.后端从authorization中拿到token后&#xff0c;通过secretKey进…

Spring Boot中使用validator如何实现接口入参自动检验

文章目录 一、背景二、使用三、举例 一、背景 在项目开发过程中&#xff0c;经常会对一些字段进行校验&#xff0c;比如字段的非空校验、字段的长度校验等&#xff0c;如果在每个需要的地方写一堆if else 会让你的代码变的冗余笨重且相对不好维护&#xff0c;如何更加规范和优…

微服务-GateWay(网关)

所谓网关是什么意思&#xff1f; 相当于就是你们小区家的保安&#xff0c;进出小区都得获得保安的同意&#xff0c;守护你们小区的生命财产健康&#xff0c;网关也是如此&#xff0c;对每个请求都严格把关&#xff0c;将合法的或者是获得权限的请求进入服务器 网关的功能&…

扩散模型实战(四):从零构建扩散模型

推荐阅读列表&#xff1a; 扩散模型实战&#xff08;一&#xff09;&#xff1a;基本原理介绍 扩散模型实战&#xff08;二&#xff09;&#xff1a;扩散模型的发展 扩散模型实战&#xff08;三&#xff09;&#xff1a;扩散模型的应用 本文以MNIST数据集为例&#xff0c;从…

智能楼宇综合布线实训室建设方案

一、楼宇智能综合布线实训室方案概述 楼宇智能综合布线实训室方案旨在为学生提供一个真实的学习和实践环境&#xff0c;以培养他们在楼宇智能综合布线领域的实际操作能力和技能。以下是一个概述&#xff1a; 1. 培养目标&#xff1a;培养学生在楼宇智能综合布线方面的综合能力…

Shader学习(三)(片元着色器)

1、在片元着色器处理漫反射 // Upgrade NOTE: replaced _World2Object with unity_WorldToObjectShader "Custom/specularfragement" {properties{_sp("Specular",color) (1,1,1,1)_shiness("Shiness",range(1,64)) 8}SubShader{pass {tags{&…

网络通信原理应用层(第五十一课)

1)DNS:域名解析系统,端口号TCP或UDP的53 2)域名注册网站 -新网 www.xinnet.com -万网-阿里云 www.net.cn -中国互联 hulian.top 配置通过域名访问网站(NETBASE第七课)_IHOPEDREAM的博客-CSDN博客 2、FTP 1)FTP概述 -文件传输协议 -控制连接:TCP 21 <

leetcode-413. 等差数列划分(java)

等差数列划分 leetcode-413. 等差数列划分题目描述双指针 上期经典算法 leetcode-413. 等差数列划分 难度 - 中等 原题链接 - 等差数列划分 题目描述 如果一个数列 至少有三个元素 &#xff0c;并且任意两个相邻元素之差相同&#xff0c;则称该数列为等差数列。 例如&#xff0…

JMeter接口测试数据分离驱动应用

步骤&#xff1a; 创建csv文件&#xff0c;编写接口测试用例 新建线程组——创建循环控制器&#xff08;循环次数填用例总数&#xff09; 创建CSV数据文件设置&#xff0c;设置参数。&#xff08;注意&#xff1a;是否允许带引号&#xff1f;&#xff1a;一定要设置为true&a…

深度学习实战48-【未来的专家团队】基于AutoCompany模型的自动化企业概念设计与设想

大家好,我是微学AI,今天给大家介绍一下深度学习实战48-【未来的专家团队】基于AutoCompany模型的自动化企业概念设计与设想,文本将介绍AutoCompany模型的概念设计,涵盖了AI智能公司的各个角色,并结合了GPT-4接口来实现各个角色的功能,设置中央控制器,公司运作过程会生成…

JMM内存模型之happens-before阐述

文章目录 一、happens-before的定义二、happens-before的规则1. 程序顺序规则&#xff1a;2. 监视器锁规则&#xff1a;3. volatile变量规则&#xff1a;4. 传递性&#xff1a;5. start()规则&#xff1a;6. join()规则&#xff1a; 一、happens-before的定义 如果一个操作hap…

【编程二三事】ES究竟是个啥?

在最近的项目中&#xff0c;总是或多或少接触到了搜索的能力。而在这些项目之中&#xff0c;或多或少都离不开一个中间件 - ElasticSearch。 今天忙里偷闲&#xff0c;就来好好了解下这个中间件是用来干什么的。 ES是什么? ​ ES全称ElasticSearch&#xff0c;是个基于Lucen…

性能优化的重要性

性能优化的重要性 性能优化的重要性摘要引言注意事项代码示例及注释性能优化的重要性 性能优化的重要性在 Java 中的体现响应速度资源利用效率扩展性与可维护性并发性能合理的锁策略线程安全的数据结构并发工具类的应用避免竞态条件和死锁 总结代码示例 博主 默语带您 Go to Ne…