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,一经查实,立即删除!

相关文章

【Vue】let、const、var的区别、适用场景

let、const、var&#xff0c;有哪些区别&#xff0c;适用场景 var 特点&#xff1a; var 是 JavaScript 中最传统的变量声明方式。具有函数作用域&#xff0c;即在函数内声明的 var 变量&#xff0c;在整个函数内都可以访问。变量提升&#xff1a;使用 var 声明的变量会被提升…

Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例

Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例 1.代码在/kernel-5.10文件夹下 2.在kernel-5.10目录下执行如下命令编译 &#xff1a; 编译之前&#xff0c;需要将 clang 导出到 PATH 环境变量&#xff1a; 如果是 Android12 执行下面这条命令 export PATH../pr…

QT3学习之qpainter学习

QImage img;QPixmap savedPixmap(sourceRect.size());QPainter savedPainter(&savedPixmap);// 使用 QPainter 从 bufferPixmap 复制指定区域savedPainter.drawPixmap(sourceRect,bufferPixmap);// 将 QPixmap 转换为 QImageQImage image savedPixmap.convertToImage();if…

web.xml常用配置

web.xml是Java Web应用程序的部署描述文件&#xff0c;它位于WEB-INF目录下。web.xml文件主要用于配置Servlet、Filter、Listener、MIME类型、欢迎页面等组件&#xff0c;以及一些Web应用的上下文参数。以下是一些常见的web.xml配置说明&#xff1a; Servlet配置&#xff1a; …

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

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

二进制、八进制、十进制和十六进制的相互转换

printf 函数 printf 函数是 C 语言中用于将格式化的数据输出到标准输出&#xff08;通常是屏幕&#xff09;的函数。它位于 stdio.h 头文件中&#xff0c;因此在使用之前需要包含该头文件。 printf 函数的格式说明符 格式说明符说明示例%d 或 %i输出或输入十进制有符号整数p…

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

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

类模板的使用方法

目录 类模板的使用方法 1.类模板语法 2.类模板和函数模板区别 3.类模板中成员函数创建时机 4.类函数对象做函数参数 5.类模板和继承 6.类模板成员函数类外实现 7.类模板分文件编写 person.hpp 实现cpp文件&#xff1a; 8.类模板与友元 9.类模板案例 MyArray.hpp …

Android SystemUI——使用Dagger2加载组件(四)

SystemUI 是 Android 系统中的一个重要模块,负责绘制系统栏(如状态栏、导航栏)、锁屏、快捷设置等用户界面元素。由于其复杂性,良好的架构设计和依赖管理对于保持代码的可维护性和扩展性至关重要。这就是 Dagger2 在此发挥重要作用的地方。 一、Dagger2介绍 Dagger2 是一个…

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…

大数据技术实训:Zookeeper集群配置

一、本地模式安装部署 1&#xff09;安装前准备 &#xff08;1&#xff09;安装jdk &#xff08;2&#xff09;拷贝Zookeeper安装包到Linux系统下 &#xff08;3&#xff09;解压到指定目录 tar -zxvf zookeeper-3.5.7.tar.gz -C /opt/module/ 2&#xff09;配置修改 &am…

一文通透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…

202309 青少年软件编程等级考试C/C++ 二级真题答案及解析(电子学会)

第 1 题 数组指定部分逆序重放 将一个数组中的前k项按逆序重新存放。例如,将数组8,6,5,4,1前3项逆序重放得到5,6,8,4,1。 时间限制:1000 内存限制:65536 输入 输入为两行: 第一行两个整数,以空格分隔,分别为数组元素的个数n(1<n<100)以及指定的k(1<=k<= n…

网管平台(进阶篇):路由器的管理实践

在当今数字化时代&#xff0c;路由器作为网络连接的核心设备&#xff0c;其管理对于确保网络的稳定、高效和安全至关重要。本文旨在深入探讨路由器管理的重要性、基本设置步骤、高级功能配置以及日常维护&#xff0c;帮助读者构建一个高效且安全的网络环境。 一、路由器管理的…

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…