9,STL——vector类

一、vector类的介绍和使用

1,了解vector

vector类的官方介绍https://cplusplus.com/reference/vector/vector/

使用STL的三个境界:能用,明理,能扩展

1). vector是表示可变大小数组的序列容器。

2). 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。

3.) 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。

4. )vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。

5. )因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。

6. )与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。

2,vector的使用

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;namespace std
{void test1(){//初始化vector<int> v1;vector<int> v2(10, 1);vector<int> v3(v2);//尾插v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);// 下标+[]遍历for (size_t i = 0; i < v1.size(); ++i){v1[i]++;}for (size_t i = 0; i < v1.size(); ++i){cout << v1[i] << " ";}cout << endl;//迭代器遍历vector<int>::iterator it = v1.begin();while (it != v1.end()){//可以修改数据(*it)--;cout << *it << " ";++it;}cout << endl;//范围for遍历for (auto e : v1){cout << e << " ";}cout << endl;}void test2(){vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);cout << v1.max_size() << endl;}void test3(){vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);//find算法,引用头文件 <algorithm>vector<int>::iterator pos = find(v1.begin(), v1.end(), 3);if (pos != v1.end()){//插入v1.insert(pos, 88);}for (auto e : v1){cout << e << " ";}cout << endl;pos = find(v1.begin(), v1.end(), 1);if (pos != v1.end()){//删除v1.erase(pos);}for (auto e : v1){cout << e << " ";}cout << endl;}void test4() {vector<int> v1;v1.push_back(8);v1.push_back(7);v1.push_back(2);v1.push_back(5);v1.push_back(9);v1.push_back(3);v1.push_back(4);v1.push_back(1);v1.push_back(6);for (auto e : v1){cout << e << " ";}cout << endl;//快排sort(v1.begin(), v1.end());for (auto e : v1){cout << e << " ";}cout << endl;//less<int> ls;//greater<int> gt;逆置函数//sort(v1.begin(), v1.end(), gt);//直接传名命对象,可以少写两行sort(v1.begin(), v1.end(), greater<int> ());for (auto e : v1){cout << e << " ";}cout << endl;string s("hello26138912634");sort(s.begin(), s.end(), greater<char>());cout << s << endl;//136 }}int main()
{//std::test1();//std::test2();//std::test3();std::test4();return 0;
}

二、vector类的模拟实现

#pragma once
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <assert.h>
using namespace std;//csy名命空间
namespace csy
{//vector模板类,类型为T,可替换template<class T>class vector{public://iterator重定义成T*,可以简化一下,//在reserve里的tmp使用//在Func里的const_iterator使用typedef T* iterator;iterator begin(){return _start;}iterator end(){return _finish;}const iterator begin() const{return _start;}const iterator end() const{return _finish;}vector():_start(nullptr), _finish(nullptr), _end_of_storag(nullptr){}//拷贝构造传统写法//vector(const vector<T>& v)//	:_start(nullptr)//	, _finish(nullptr)//	, _end_of_storag(nullptr)//{//	//开空间//	reserve(v.size());//	//拷贝数据//	for (auto e : v)//	{//		push_back(e);//	}//}//同值构造vector(size_t n, const T& val = T()){reserve(n);for (size_t i = 0; i < i; ++i){push_back(val);}}//拷贝构造的现代写法,区间构造,swap写入template <class InputIterator>vector(InputIterator first, InputIterator last):_start(nullptr), _finish(nullptr), _end_of_storag(nullptr){while (first != last){push_back(*first);++first;}}void swap(vector<T>& v){std::swap(_start,v._start);std::swap(_finish,v._finish);std::swap(_end_of_storag,v._end_of_storag);}vector(const vector<T>& v){//开空间vector<T> tmp(v.begin(),v.end());//拷贝数据swap(tmp);}~vector(){delete[] _start;_start = _finish = _end_of_storag = nullptr;}//提供capacity和size和reserve和v[i]size_t capacity() const{return _end_of_storag - _start;}size_t size() const{return _finish - _start;}void reserve(size_t n){if (n > capacity()){//开辟n大小的空间T* tmp = new T[n];//拷贝if (_start){memcpy(tmp, _start, sizeof(T)*size());delete[] _start;}//替换size(),避免_start改变导致size()改变size_t sz = size();//类成员变量赋值更新_start = tmp;_finish = _start + sz;_end_of_storag = _start + n;}}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为8个元素,12345678,size要重置成长度n//1,如果n > 15 需要扩容 + 初始化//2,如果n > 8 && n <= 15 初始化//3,如果n < 8 删除数据void resize(size_t n, const T& val = T()){if (n > capacity()){reserve(n);}if (n > size()){//初始化填值while (_finish < _start + n){*_finish = val;++_finish;}}else{_finish = _start + n;}}//加const避免引用临时变量void push_back(const T& x){if (_finish == _end_of_storag){reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;++_finish;}void pop_back(){assert(_finish > _start);--_finish;}//v.insert(v.begin(), 1);//pos不要传引用,不能修改引用值iterator insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);//扩容if (_finish == _end_of_storag){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + len;}//挪动后半段数据//扩容后,pos还指向旧空间,pos变成野指针,也叫做迭代器的失效//所以扩容后要重置positerator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}//插入*pos = x;++_finish;return pos;}//结论:insert/erase pos位置,不要直接访问pos//一定要更新,直接访问,可能各种出乎意料的结果//认为pos失效,不要访问iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);//挪动后面的往前一个位置覆盖iterator begin = pos + 1;while (begin < _finish){*(begin - 1) = *begin;++begin;}--_finish;return pos;}T& front(){assert(size() > 0);return *_start;}T& back(){assert(size() > 0);return *(_finish - 1);}private:iterator _start;iterator _finish;iterator _end_of_storag;};void Func(const vector<int>& v){//注意使用const迭代器vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;for (auto e : v){cout << e << " ";}cout << endl;}void test_vector1(){double d = 2.2;//int& i = d;const int& i = d;vector<string> v;v.push_back("xxxxx");for (size_t i = 0; i < v.size(); ++i){cout << v[i] << " ";}cout << endl << endl;;}void test_vector2(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);for (size_t i = 0; i < v.size(); ++i){cout << v[i] << " ";}cout << endl << endl;}void test_vector3(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;v.pop_back();v.pop_back();for (auto e : v){cout << e << " ";}cout << endl;Func(v);}void test_vector4(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);for (size_t i = 0; i < v.size(); ++i){cout << v[i] << " ";}cout << endl << endl;auto p = find(v.begin(), v.end(), 3);if (p != v.end()){//p不要再次使用,可能失效了v.insert(p, 30);//cout << *p << endl;//v.insert(p, 40);}for (auto e : v){cout << e << " ";}cout << endl;}void test_vector5(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(4);v.push_back(3);v.push_back(4);v.push_back(5);//删除所有的偶数auto it = v.begin();while (it != v.end()){	//错误用法//if (*it % 2 == 0)//{//	v.erase(it);//}//++it;//正确用法if (*it % 2 == 0){it = v.erase(it);}else{++it;}}for (auto e : v){cout << e << " ";}cout << endl;}void test_vector6(){std::vector<int> v;v.reserve(10);v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);//在所有的偶数前面插入偶数的2倍auto it = v.begin();while (it != v.end()){if (*it % 2 == 0){it = v.insert(it, *it * 2);++it;++it;}else{++it;}}for (auto e : v){cout << e << " ";}cout << endl;}//浅拷贝,析构两次,指向同一空间,一个对象修改影响两个对象//深拷贝,开辟新空间,指向新空间void test_vector7() {//普通构造vector<int> v1;v1.push_back(1);for (auto e : v1){cout << e << " ";}//拷贝构造vector<int> v2(v1);for (auto e : v2){cout << e << " ";}cout << endl;//内置类型也有构造int i = 6;int j = int();int k = int(22);cout << i << " " << j << " " << k << endl;}void test_vector8(){vector<int> v1;v1.resize(10, 0);for (auto e : v1){cout << e << " ";}cout << endl << endl;vector<int> v2;v2.reserve(10);v2.push_back(1);v2.push_back(2);v2.push_back(3);v2.push_back(4);v2.push_back(5);v2.resize(8, 8);for (auto e : v2){cout << e << " ";}cout << endl << endl;v2.resize(20, 20);for (auto e : v2){cout << e << " ";}cout << endl << endl;}
}

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

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

相关文章

基于考研概率论知识解读 Transformer:为何自注意力机制要除以根号 dk

Transformer自注意力机制中除以 d k \sqrt{d_k} dk​ ​深度剖析 【 Transformer 系列&#xff0c;故事从 d k \sqrt{d_k} dk​ ​说起】 LLM这么火&#xff0c;Transformer厥功甚伟&#xff0c;某天心血来潮~&#xff0c;再去看看&#xff01; 它长这个样子&#xff1a; 深入…

Kafka权威指南(第2版)读书笔记

目录 Kafka生产者——向Kafka写入数据生产者概览创建Kafka生产者bootstrap.serverskey.serializervalue.serializer 发送消息到Kafka同步发送消息 Kafka生产者——向Kafka写入数据 不管是把Kafka作为消息队列、消息总线还是数据存储平台&#xff0c;总是需要一个可以往Kafka写…

python识别图片中指定颜色的图案并保存为图片

示例代码&#xff1a; def chuli(color):import cv2import numpy as np# 定义颜色名称到HSV阈值范围的映射color_thresholds {red: ([0, 100, 100], [10, 255, 255], [160, 100, 100], [180, 255, 255]),yellow: ([20, 100, 100], [30, 255, 255]),blue: ([90, 100, 100], [1…

golang 环境变量配置

一、GoLand显示环境如下 修改环境变量 新建系统变量 GOROOT&#xff1a; D:\ENSPACE\golandsdk\1.23.1\go1.23.1新建系统变量 GOPATH&#xff1a;工作目录&#xff08;在下面目录下新建目录&#xff1a;src,项目工程目录都要建在src下如&#xff1a;demo1 demo2&#xff09; D…

当自动包布机遇上Profinet转ModbusTCP网关,“妙啊”,工业智能“前景无限

在自动化控制技术日新月异的当下&#xff0c;Profinet与ModbusTCP这两种协议在工业通信领域占据着举足轻重的地位。ModbusTCP是基于以太网的串行通信协议&#xff0c;而Profinet则是依托工业以太网的现场总线协议。它们在数据传输速度、实时性表现以及兼容性等方面各具特色。不…

Redis的过期策略、内存淘汰机制

Redis只能存5G数据&#xff0c;可是你写了10G&#xff0c;那会删5G的数据。怎么删的&#xff1f;还有&#xff0c;你的数据已经设置了过期时间&#xff0c;但是时间到了&#xff0c;为什么内存占用率还是比较高? 一、Redis的过期策略 Redis采用的是定期删除惰性删除策略。 1…

一文通透OpenVLA及其源码剖析——基于Prismatic VLM(SigLIP、DinoV2、Llama 2)及离散化动作预测

前言 当对机器人动作策略的预测越来越成熟稳定之后(比如ACT、比如扩散策略diffusion policy)&#xff0c;为了让机器人可以拥有更好的泛化能力&#xff0c;比较典型的途径之一便是基于预训练过的大语言模型中的广泛知识&#xff0c;然后加一个policy head(当然&#xff0c;一开…

MySQL数据库(SQL分类)

SQL分类 分类全称解释DDLData Definition Language数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库&#xff0c;表&#xff0c;字段&#xff09;DMLData Manipulation Language数据操作语言&#xff0c;用来对数据库表中的数据进行增删改DQLData Query Languag…

word-break控制的几种容器换行行为详解

word-break 属性在控制换行行为时需要根据语言判断&#xff0c;对于中文 一个字符就是一个单词&#xff0c;字符换行不影响阅读理解&#xff0c;而对于英文来说&#xff0c;多个连续的字符才会是一个单词&#xff0c;例如中文的 早 英文为 morning。 morning7个字符才算一个单词…

国内源快速在线安装qt5.15以上版本。(10min安装好)(图文教程)

参考文章&#xff1a;Qt6安装教程——国内源-CSDN博客 1、在国内源上下载qt在线安装工具 NJU Mirror 2、 将下载好的在线安装工具&#xff0c;放到C盘根目录&#xff0c; 2.1 打开windows Powershell&#xff08;WinX&#xff09;&#xff0c;下边那个最好。 输入两条指令&a…

JVM虚拟机的组成 笼统理解 六大部分 类加载子系统 运行时数据区 执行引擎 本地接口 垃圾回收器 线程工具

目录 JVM虚拟机的组成&#xff1a;概述 JVM虚拟机的组成&#xff1a;详细解析 1. 类加载子系统 2. 运行时数据区 3. 执行引擎 4. 本地接口 5. 垃圾回收器 6. 线程管理与调试工具 概述 JVM&#xff08;Java Virtual Machine&#xff09;是一个虚拟计算机&#xff0c;执行…

2025 年 UI 大屏设计新风向

在科技日新月异的 2025 年&#xff0c;UI 大屏设计领域正经历着深刻的变革。随着技术的不断进步和用户需求的日益多样化&#xff0c;新的设计风向逐渐显现。了解并掌握这些趋势&#xff0c;对于设计师打造出更具吸引力和实用性的 UI 大屏作品至关重要。 一、沉浸式体验设计 如…

虚拟拨号技术(GOIP|VOIP)【基于IP的语音传输转换给不法分子的境外来电披上一层外衣】: Voice over Internet Protocol

文章目录 引言I 虚拟拨号技术(GOIP|VOIP)原理特性:隐蔽性和欺骗性II “GOIP”设备原理主要功能III 基于IP的语音传输 “VOIP” (Voice over Internet Protocol)IV “断卡行动”“断卡行动”目的电信运营商为打击电诈的工作V 知识扩展虚拟号保护隐私虚拟运营商被用于拨打骚扰…

算法-查找数组对角线上最大的质数

力扣题目&#xff1a;2614. 对角线上的质数 - 力扣&#xff08;LeetCode&#xff09; 给你一个下标从 0 开始的二维整数数组 nums 。 返回位于 nums 至少一条 对角线 上的最大 质数 。如果任一对角线上均不存在质数&#xff0c;返回 0 。 注意&#xff1a; 如果某个整数大于…

js:正则表达式

目录 正则表达式的语法 定义 检测 检索 元字符 边界符 量词 字符类 表单判断案例 修饰符 过滤敏感词 正则表达式是一种用于匹配和操作文本的强大工具&#xff0c;它是由一系列字符和特殊字符组成的模式&#xff0c;用于描述要匹配的文本字符组合模式 正则表达式是一…

Excel数据叠加生成新DataFrame:操作指南与案例

目录 一、准备工作 二、读取Excel文件 三、数据叠加 四、处理重复数据&#xff08;可选&#xff09; 五、保存新DataFrame到Excel文件 六、案例演示 七、注意事项 八、总结 在日常数据处理工作中&#xff0c;我们经常需要将不同Excel文档中的数据整合到一个新的DataFra…

HarmonyOS NEXT开发进阶(六):HarmonyOS NEXT实现嵌套 H5 及双向通信

文章目录 一、前言二、鸿蒙应用加载Web页面2.1 加载网络地址页面2.2 加载本地H5页面 三、实现Web组件 H5 层与鸿蒙应用层进行相互通讯3.1 鸿蒙应用向 H5 页面发送数据3.2 H5页面向鸿蒙应用发送数据 四、拓展阅读 一、前言 随着HarmonyOS NEXT的快速发展&#xff0c;越来越多的…

Linux Top 命令 load average 指标解读

前言 作为平台开发的同学&#xff0c;维护平台稳定性是我们最基本的工作职责&#xff0c;下面主要介绍下top 命令里 &#xff0c;load average 这个指标如何去衡量机器负载程度。 概念介绍 load average 是系统在过去 1 分钟、5 分钟、15 分钟 的平均负载&#xff0c;它表示运…

uni-app编写微信小程序使用uni-popup搭配uni-popup-dialog组件在ios自动弹出键盘。

uni-popup-dialog 对话框 将 uni-popup 的type属性改为 dialog&#xff0c;并引入对应组件即可使用对话框 &#xff0c;该组件不支持单独使用 示例 <button click"open">打开弹窗</button> <uni-popup ref"popup" type"dialog"…

国产编辑器EverEdit - 扩展脚本:新建同类型文件(避免编程学习者反复新建保存练习文件)

1 扩展脚本&#xff1a;在当前文件目录下新建同类型文件 1.1 应用场景 用户在进行编程语言学习时&#xff0c;比如&#xff1a;Python&#xff0c;经常做完一个小练习后&#xff0c;又需要新建一个文件&#xff0c;在新建文件的时候&#xff0c;不但要选择文件类型&#xff0c…