C++ vector顺序表模拟实现

目录

前言:

模拟实现:

 构造函数:

析构函数:

容量调整(reserve):

 resize函数:

尾插(push_back):

 尾删(pop_back):

插入(insert):

 销毁(erase):

[]重载:

交换(swap):

=重载:

 代码


前言:

  在学习vector的功能后,我自己模拟实现了一些vector的基本功能,这篇文章用来分享一下,也便于我后续的复习。

模拟实现:

  总所周知vector中迭代器是遍历vector的重要工具,既然我这里只是简单的模拟,那迭代器就用简单的指针来模拟,先typedef一下:

vector可以装很多类型,int,char,float,string......等,所以我们应该写一个类模板,大致框架如下:

 

先简单确定3个成员变量:

_start指向vector最前面的元素

_finish指向vector内所有有效数据的后一个

_endofstorage指向vector容量的最后一个 

给缺省值都为空指针: 

然后再来几个简单,但又很重要的函数:

 构造函数:

我这里只实现3种常用的构造函数:

1.vector<int> v(n,val):   v里面有3个元素,全初始化成val。

 

 这里的push_back函数也就是尾插函数后面会实现,这里先复用。

2.vector<int> v1(v2):   这个也就是拷贝构造函数:

同样这里的reserve函数也就是容量调整函数后面实现。

3.vector<int> v1(v2.begin(),v2.end()):   用另一个类的迭代器初始化:

注意这里另一个类不一定是vector,也有可能是string等,所以我们需要写一个模板函数:

 

析构函数:

这个很简单: 

容量调整(reserve):

思路请看注释,注意这里一定要记录旧空间size的大小后才能更新finish 

 resize函数:

功能:将有效数据个数调整到n,如果n<原来有效数据个数,则舍去多余的,如果n>有效数据个数,则多出的空间用val填充:

尾插(push_back):

尾插需要注意的是,尾插前要检查一下容量,不够的话就需要扩容:

 尾删(pop_back):

插入(insert):

注意,如果要扩容的话,就必须先记录pos的位置,如上图用len记录,扩容完再更新pos位置,因为扩容会指向新的空间,如果不更新pos,pos就还是指向旧的空间,但旧的空间已经被释放了,就会引起程序崩溃。 

 销毁(erase):

删除pos位置的数据,直接让pos后的数据挪动覆盖即可:

[]重载:

这里为了方便const类使用,所以多写了个const函数:

交换(swap):

 直接调用库里的swap函数交换3个指针即可

=重载:

 因为这里用的swap是我自己写的成员函数,所以只需传参v,就可完成交换,因为成员函数第一个参数是隐含的this指针。还有个巧妙的地方是这里赋值重载用的是传参输入,而不是传引用,这样做的好处,就是巧妙利用了拷贝,我举个例子如下:

v3=v1;将v1赋值给v3,进入上述函数后,v就是v1的拷贝,然后交换v3和v,这样就不会修改到v1的情况下,还赋值给了v3。

 代码:

#pragma once
#include<string.h>
#include<iostream>
#include<assert.h>
using namespace std;
namespace sxk
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}iterator begin()const{return _start;}iterator end()const{return _finish;}size_t size()const{return _finish - _start;}size_t capacity()const{return _endofstorage - _start;}//v2(v1)vector(const vector<T>& v){reserve(v.capacity());//不管咋样先把容量变为一样的for (auto x : v){push_back(x);}}vector(int n, const T& val = T())//缺省值为匿名模板类,因为val也可能是别的类{reserve(n);for (int i = 0;i < n;i++){push_back(val);}}vector(){}bool empty(){return _start == _finish;}~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);}T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos)const{assert(pos < size());return _start[pos];}vector<T>& operator=(vector<T> v){swap(v);return *this;}void reserve(size_t n)//将容量调整到n(这里只实现扩容){if (n > capacity())//如果容量不够,扩容{T* tmp = new T[n];//先开辟容量为n的新空间size_t old_size = size();//记录原来空间的size,方便后续找到新空间finish的位置memcpy(tmp, _start, size() * sizeof(T));//将数据拷贝到新空间delete[] _start;//释放旧空间_start = tmp;//指向新空间_finish = tmp + old_size;_endofstorage = tmp + n;}}void resize(size_t n, const T& val = T())//因为val可以为别的类,所以用匿名模板对象当缺省值{if (n > size())//如果n大于原有效数据个数{reserve(n);//先扩容while (_finish != _start + n)//开始用val填充多的空间{*_finish = val;++_finish;}}else//如果n小于等于原有效数据个数{_finish = _start + n;//直接调整_finish的位置即可}}void push_back(const T& val){if (_finish == _endofstorage)//如果容量不够{reserve(capacity() == 0 ? 4 : capacity() * 4);//扩容,防止原来容量为0,扩容不上}*_finish = val;//尾插_finish++;//更新finish}void pop_back(){assert(!empty());//防止vector为空--_finish;//直接--finish即可}void insert(iterator pos,const T& val){if (_finish == _endofstorage)//如果要扩容{size_t len = pos - _start;//记录pos位置方便后续更新reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + len;//扩容完更新pos}iterator it = _finish - 1;//it初始指向最后一个元素while (it >= pos)//开始移动数据,把pos位置腾出来{*(it + 1) = *it;--it;}*pos = val;++_finish;}iterator erase(iterator pos)//删除pos位置的值{iterator it = pos + 1;//it初始指向pos后面一个位置的元素while (it <= _finish){*(it - 1) = *it;it++;}--_finish;return pos;}template<class Inputiterator>//使用迭代器初始化vector(Inputiterator first, Inputiterator last){while (first != last){push_back(*first);first++;}}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;};template<class T>void print_vector(vector<T>& v){for (int i = 0;i < v.size();i++){cout << v[i] << ' ';}cout << endl;}
}

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

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

相关文章

C++ | Leetcode C++题解之第8题字符串转换整数atoi

题目&#xff1a; 题解&#xff1a; class Automaton {string state "start";unordered_map<string, vector<string>> table {{"start", {"start", "signed", "in_number", "end"}},{"signed…

如何判断超级充电测试的性能

超级充电测试是电动汽车充电设备性能评估的重要环节&#xff0c;其性能的好坏直接影响到电动汽车的充电效率和使用寿命。以下是判断超级充电测试性能的几个关键因素&#xff1a;这是衡量超级充电测试性能的最直接指标&#xff0c;充电速度快意味着电动汽车可以在更短的时间内完…

商业分析思维与实践:用数据分析解决商业问题

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

日期时间相关的类

分界线jdk8 jdk8之前和之后分别提供了一些日期和时间的类&#xff0c;推荐使用jdk8之后的日期和时间类 Date类型 这是一个jdk8之前的类型&#xff0c;其中有很多方法已经过时了&#xff0c;选取了一些没有过时的API //jdk1.8之前的日期 Date Date date new Date(); // 从1970年…

区块链的网络架构有哪些?

区块链技术的兴起正在深刻地改变着互联网的格局。它不仅提供了去中心化、数据透明、难以篡改等优势&#xff0c;还为各种应用场景提供了新的可能性。为了更好地理解区块链&#xff0c;我们需要深入探讨其网络架构。 区块链网络架构主要由以下几个部分组成&#xff1a; 1. 区块…

Web 前端性能优化之五:构建优化

4、构建优化 资源的合并与压缩所涉及的优化点包括两方面&#xff1a;一方面是减少HTTP的请求数量&#xff0c;另一方面是减少HTTP请求资源的大小。 1、HTML 压缩 1、什么是 HTML 压缩 百度首页部分 HTML 源代码 谷歌首页部分 HTML 源代码 虽然这些格式化的字符能带来很好的代…

SpringBoot及其特性

0.前言 Spring 框架提供了很多现成的功能。那么什么是 Spring Boot&#xff1f;使用 Spring 框架&#xff0c;我们可以避免编写基础框架并快速开发应用程序。为了让 Spring 框架提供基础框架&#xff0c;我们需要向 Spring 框架描述有关我们的应用程序及其组件的信息。 不只是…

OpenAI Sora:浅析文生视频模型Sora以及技术原理简介

一、Sora是什么&#xff1f; Sora官方链接&#xff1a;https://openai.com/sora 视频模型领头羊Runway Gen 2、Pika等AI视频工具&#xff0c;都还在突破几秒内的连贯性&#xff0c;而OpenAI&#xff0c;已经达到了史诗级的纪录。 OpenAI&#xff0c;永远快别人一步&#xff0…

C语言面试题之判定字符是否唯一

判定字符是否唯一 实例要求 实现一个算法&#xff0c;确定一个字符串 s 的所有字符是否全都不同 实例分析 1、使用一个大小为 256 的bool数组 charSet 来记录字符是否出现过&#xff1b;2、遍历字符串时&#xff0c;如果字符已经在数组中标记过&#xff0c;则返回 false&a…

Golang 开发实战day08 - Multiple Return values

Golang 教程08 - Multiple Return values 1. Multiple return values 1.1 如何理解多个返回值&#xff1f; Go语言中的多返回值&#xff0c;就像你听了一首歌曲yellow&#xff0c;可以从歌曲里反馈出忧郁和害羞&#xff01;Goland的多个返回值就类似于如此&#xff0c;设定一…

LangChain - OpenGPTs

文章目录 MessageGraph 消息图认知架构AssistantsRAGChatBot 持久化配置新模型新工具astream_events总结 关键链接&#xff1a; OpenGPT GitHub 存储库YouTube 上的 OpenGPT 演练LangGraph&#xff1a;Python、JS 两个多月前&#xff0c;在 OpenAI 开发日之后&#xff0c;我们…

检定重型铸铁平台的方法——北重厂家

检定重型铸铁平台的方法一般包括以下几个方面&#xff1a; 1.外观检查&#xff1a;检查平台表面是否平整和光滑&#xff0c;是否有明显的裂纹、磨损或损坏等情况。 2.尺寸检测&#xff1a;使用专用的测量工具&#xff0c;如千分尺、测微计等&#xff0c;测量平台的尺寸&#x…

Day107:代码审计-PHP模型开发篇MVC层RCE执行文件对比法1day分析0day验证

目录 MVC 架构 CNVD-代码执行1day-lmxcms1.40版本 CNVD-命令执行1day-baijiacms4.1.4版本 知识点&#xff1a; 1、PHP审计-MVC开发-RCE&代码执行 2、PHP审计-MVC开发-RCE&命令执行 3、PHP审计-MVC开发-RCE&文件对比 MVC 架构 MVC流程&#xff1a; Controller截…

支持向量机(SVM)白话之个人理解(学习记录)

本文仅有文字理解部分&#xff0c;没有相应的数学公式推导过程&#xff0c;便于新手理解。 一、什么是支持向量机 首先我们看下面这张图&#xff0c;在图中圆形和三角形分别代表不同的数据类型&#xff0c;如何画出一条直线使两者能够显著地区分开来呢&#xff1f; 答案可以多…

成都污水处理设备厂家怎么选?

在选择成都的污水处理设备厂家时&#xff0c;可以从以下几个方面来进行评估和选择&#xff1a; 1. **公司资质**&#xff1a;首先需要确认厂家是否拥有合法的营业执照、环保设备生产许可证及相关的环保工程资质。 2. **技术实力**&#xff1a;了解厂家是否具备雄厚的技术研发实…

通过自动化部署消除人为操作:不断提高提交部署比率

三十年后&#xff0c;我仍然热爱成为一名软件工程师。事实上&#xff0c;我最近读了威尔拉森&#xff08;Will Larson&#xff09;的《员工工程师&#xff1a;超越管理轨道的领导力》&#xff0c;这进一步点燃了我以编程方式解决复杂问题的热情。知道雇主继续照顾员工、原则和杰…

Goingpub国自然基金-免费查询

可进行年份、学部、项目类别等检索&#xff0c;支持生成主题词汇总分析报告。 最最最关键&#xff0c;免费&#xff0c;只需要你注册登录一下&#xff0c;防止被爬虫侵扰。 界面简单&#xff0c;实用&#xff0c;支持模糊搜索&#xff0c;包含最新2023年数据&#xff0c;共56…

Python异常值分析

异常值分析是检验数据是否有录入错误以及含有不合常理的数据。忽视异常值的存在是十分危险的&#xff0c;不加剔除地把异常值包括进数据的计算分析过程中&#xff0c;对结果会产生不良影响&#xff1b;重视异常值的出现&#xff0c;分析其产生的原因&#xff0c;常常成为发现问…

从0开始学人工智能测试节选:Spark -- 结构化数据领域中测试人员的万金油技术(一)

回顾一下模型的生命周期 需要注意的是&#xff0c;在这个流程中&#xff0c;测试至少要参与的以下的活动&#xff1a; 离线的模型测试线上线下一致性测试数据质量测试模型的线上质量监控建模过程的功能/性能等测试 可以看出来测试人员需要做的事情其实不少&#xff0c;整个建模…

Python景区票务人脸识别系统(V2.0),附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…