C++ vector

目录

一、vector的介绍及使用

1.1 vector的介绍

1.1.1 认识vector

1.1.2 成员类型​​​​​​​

1.1.3 成员函数一览

1.1.4 非成员函数重载 

1.2 vector的使用

1.2.1 构造、析构与赋值操作符重载

1.2.2 reserve 与 resize

1.2.3 insert、erase 与 find

extra train

1. 二叉树的前序遍历

2. 只出现一次的数字

3. 杨辉三角

二、vector的深度剖析及模拟实现

2.1 vector的深度剖析         

2.1.1 memcpy 浅拷贝问题

2.2.2 iterator 迭代器失效问题        

insert 迭代器失效

erase 迭代器失效        

2.2 vector的模拟实现        

extra train   

1. 只出现一次的数字 II    

2. 电话号码的字母组合  



一、vector的介绍及使用

注意:作者能力有限,无法根据英文文档翻译出较为准确的中文意思,vector具体相关知识参考网站  cplusplus.com/reference/vector/vector/        

1.1 vector的介绍

1.1.1 认识vector

vector是表示大小可变的数组的序列容器
1. 与数组类似,vector也采用的连续存储空间来存储元素,可以采用下标对vector的元素进行访问,但是它的大小是可以动态改变的,而且它的大小会被容器自动处理
2 本质上,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小以此来增加存储空间
3 vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大(不同的库采用不同的策略权衡空间的使用和重新分配)
4 与其它动态序列容器相比(deque、 list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好

1.1.2 成员类型

1.1.3 成员函数一览

vector的许多成员函数都与string类似(左边一栏为函数名,右边一栏为简要作用的描述)

        

1.1.4 非成员函数重载 

        

1.2 vector的使用

注意:一些常见的、通用的不再赘述(例如:size()求大小、capacity()求容量、~vector()析构、push_back()尾插 等不作详细介绍,主要介绍接口有些复杂但是比较常用的一些函数)

1.2.1 构造、析构与赋值操作符重载

接口展示:

void test_vector1()
{// 构造	Construct vector vector<int> v1;vector<int> v2(10, 0);vector<int> v3(v2.begin(), v2.end());string str("hello world");vector<int> v4(str.begin(), str.end());vector<int> v5(v4);// 遍历 operator[]  迭代器iterator  循环for(size_t)  范围for(auto)for (size_t i = 0; i < v3.size(); i++){cout << v3[i] << " ";}cout << endl;vector<int>::iterator it = v4.begin();while (it != v4.end()){cout << *it << " ";it++;}cout << endl;for (auto e : v5){cout << e << " ";}cout << endl;// 析构// ~vector()// 赋值vector<int> v7(7, 0);vector<int> v8(8, 0);v8 = v7;v7 = vector<int>();cout << "Size of v7: " << int(v7.size()) << endl;cout << "Size of v8: " << int(v8.size()) << endl;
}output:
0 0 0 0 0 0 0 0 0 0
104 101 108 108 111 32 119 111 114 108 100
104 101 108 108 111 32 119 111 114 108 100
Size of v7: 0
Size of v8: 7

1.2.2 reserve 与 resize

接口展示:

void test_vector2()
{size_t sz;vector<int> v;// v.reserve(100);// v.resize(100);sz = v.capacity();cout << "making v grow:\n";for (int i = 0; i < 100; ++i){v.push_back(i);if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}void test_vector3()
{vector<int> v1;cout << v1.max_size() << endl;vector<int> v;v.reserve(100);		// size = 0    capacity 100v.resize(100);		// size = 100  capacity 100for (int i = 0; i < 100; i++){v[i] = i;}for (auto e : v){cout << e << " ";}cout << endl;
}output:
making v grow:
capacity changed: 1
capacity changed: 2
capacity changed: 3
capacity changed: 4
capacity changed: 6
capacity changed: 9
capacity changed: 13
capacity changed: 19
capacity changed: 28
capacity changed: 42
capacity changed: 63
capacity changed: 94
capacity changed: 141
1073741823
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

1.2.3 insert、erase 与 find

接口展示:        

void test_vector4()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);// insertfor (auto e : v){cout << e << " ";}cout << endl;v.insert(v.begin(), 0);for (auto e : v){cout << e << " ";}cout << endl;// findauto it = find(v.begin(), v.end(), 3);if (it != v.end()){v.insert(it, 30);}for (auto e : v){cout << e << " ";}cout << endl;it = find(v.begin(), v.end(), 3);if (it != v.end()){v.erase(it);}for (auto e : v){cout << e << " ";}cout << endl;// clear & shrink_to_fitcout << v.size() << endl;cout << v.capacity() << endl;v.clear();			// size = 0v.shrink_to_fit();	// size == 0 ? capacity = 0 : capacity--cout << v.size() << endl;cout << v.capacity() << endl;
}output:
1 2 3 4
0 1 2 3 4
0 1 2 30 3 4
0 1 2 30 4
5
6
0
0

extra train

1. 二叉树的前序遍历

144. 二叉树的前序遍历 - 力扣(LeetCode)

// 144.二叉树的前序遍历class Solution {
public:void preorder(TreeNode* root, vector<int>& v){if(root == nullptr)return;v.push_back(root->val);preorder(root->left, v);preorder(root->right, v);}vector<int> preorderTraversal(TreeNode* root) {vector<int> vec;preorder(root, vec);return vec;}
};

2. 只出现一次的数字

136. 只出现一次的数字 - 力扣(LeetCode)

//136. 只出现一次的数字class Solution {
public:int singleNumber(vector<int>& nums) {int val = 0;for (auto e : nums){val ^= e;}return val;}
};

3. 杨辉三角

118. 杨辉三角 - 力扣(LeetCode)     

//118. 杨辉三角class Solution {
public:vector<vector<int>> generate(int numRows) {// 二维数组vector<vector<int>> vv;vv.resize(numRows);for(size_t i = 0; i < vv.size(); i++){vv[i].resize(i+1, 0);vv[i][0] = vv[i][vv[i].size()-1] = 1;}for(size_t i = 0; i < vv.size(); i++){for(size_t 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的深度剖析及模拟实现

2.1 vector的深度剖析         

2.1.1 memcpy 浅拷贝问题

void reserve(size_t n)
{if (n > capacity()){	// 创建新的空间T* tmp = new T[n];size_t sz = size();if (_start){// 拷贝数据 并 删除旧的空间memcpy(tmp, _start, sizeof(T) * n);	//浅拷贝delete[] _start;}_start = tmp;_finish = _start + sz;_endofstorage = _start + n;}
}

        

        

2.2.2 iterator 迭代器失效问题        

insert 迭代器失效

void insert(iterator pos, const T& x)
{assert(pos >= _start);assert(pos <= _finish);if (_finish == _endofstorage){reserve(capacity() == 0 ? 4 : capacity() * 2);}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;
}

        

为了防止迭代器失效,需要我们记录_start与pos的相对位置,及时更新pos。具体的实现方法见<vector的模拟实现>

erase 迭代器失效        

void erase(iterator pos)
{assert(pos >= _start);assert(pos <= _finish);vector<int>::iterator it = pos - 1;while (it < _finish){*(it - 1) = *it;++it;}--_finish;
}void test_vector()
{// 测试三组用例// 1 2 3 4 5        output: 1 3 5// 1 2 3 4 5 6      output: 崩溃// 2 2 3 4 5        output: 2 3 5std::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);//v.push_back(6);for (auto e : v){cout << e << " ";}cout << endl;auto it = v.begin();while (it != v.end()){if (*it % 2 == 0){v.erase(it);// it = v.erase(it);}++it;}for (auto e : v){cout << e << " ";}cout << endl;
}erase后的迭代器无法正常使用,为了防止出现问题,我们可以记录erase后的迭代器并返回接受,更新原来的迭代器。具体的实现方法见<vector的模拟实现>

        

2.2 vector的模拟实现        

#pragma once
#include <assert.h>namespace myvector
{// 模板template<class T>class vector{public:// 迭代器(反向迭代器未实现)typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const {return _start;}const_iterator end() const{return _finish;}vector()	// 注意:该构造函数不能删去,有其它函数需要使用它{}template <class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}// size_t 类型的 nvector(size_t n, const T& val = T()){// const T& val 的缺省参数最好还是给 T()reserve(n);	// 扩容,检查都交给reservefor (size_t i = 0; i < n; i++){push_back(val);}}// int 类型的 n(为了更好地匹配使用)vector(int n, const T& val = T()){reserve(n);for (int i = 0; i < n; i++){push_back(val);}}// copy构造vector(const vector<T>& v){reserve(v.capacity());for (auto& e : v){push_back(e);}}// 初始化列表vector():_start(nullptr),_finish(nullptr),_endofstorage(nullptr){}// 析构~vector(){delete[] _start;_start = _finish = _endofstorage = nullptr;}void swap(vector<T>& v){// “swap”前面加上“std::”确保调用库中的swapstd::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);}// 赋值操作符重载vector<T>& operator=(vector<T> tmp){// 赋值需要传参,传参调用copy构造// 实际上是copy构造帮助完成了赋值swap(tmp);return *this;}void push_back(const T& x){/*if (_finish == _endofstorage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;++_finish;*/// 借用 insert insert(end(), x);}// []操作符重载(可读可写)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 reserve(size_t n){if (n > capacity()){	// 创建新的空间T* tmp = new T[n];size_t sz = size();if (_start){// 拷贝数据 并 删除旧的空间//memcpy(tmp, _start, sizeof(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, T val = T())	两种写法是一致的void resize(size_t n, const T& val = T()){if (n <= size()){_finish = _start + n;}else{reserve(n);while (_finish < _start + n){*_finish = val;_finish++;}}}// 插入void insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);if (_finish == _endofstorage){size_t len = pos - _start;	// reserve扩容导致迭代器pos失效(pos指向的原来的_start已经释放了)reserve(capacity() == 0 ? 4 : capacity() * 2);// 及时更改pospos = _start + len;			}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;}// 删除(返回值用于解决迭代器失效的问题)iterator erase(iterator pos){assert(pos >= _start);assert(pos <= _finish);vector<int>::iterator it = pos - 1;while (it < _finish){*(it - 1) = *it;++it;}--_finish;return pos;}private:iterator _start;iterator _finish;iterator _endofstorage;};
}

        

extra train   

1. 只出现一次的数字 II    

137. 只出现一次的数字 II - 力扣(LeetCode)        

//137. 只出现一次的数字 II
// 数电解法
class Solution137I {
public:int singleNumber(vector<int>& nums){int a = 0, b = 0;for (auto e : nums){b = ~a & (b ^ e);a = ~b & (a ^ e);}return b;}
};// 按位解法
class Solution137II {
public:int singleNumber(vector<int>& nums){int ans = 0;for (int i = 0; i < 32; ++i){int total = 0;for (auto num : nums){// 取出num的第i个二进制位total += ((num >> i) & 1);  // & 按位与}if (total % 3){ans |= (1 << i);    // | 按位或}}return ans;}
};

2. 电话号码的字母组合  

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

// 17. 电话号码的字母组合class Solution17 {const char* numStrArr[10] = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
public:void Combine(const string& digits, int i, vector<string>& ret, string combineStr){if (i == digits.size()){ret.push_back(combineStr);return;}int num = digits[i] - '0';string str = numStrArr[num];for (size_t j = 0; j < str.size(); j++){Combine(digits, i + 1, ret, combineStr + str[j]);}}vector<string> letterCombinations(string digits){vector<string> v;if (digits.empty()){return v;}string str;Combine(digits, 0, v, str);return v;}
};

        

        


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

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

相关文章

工厂人员作业行为动作识别检测算法

工厂人员作业行为动作识别检测算法通过yolov7python深度学习算法框架模型&#xff0c;工厂人员作业行为动作识别检测算法实时识别并分析现场人员操作动作行为是否符合SOP安全规范流程作业标准&#xff0c;如果不符合则立即抓拍告警提醒。Python是一种由Guido van Rossum开发的通…

Nginx详解 三:高级配置

文章目录 1. 网页的状态页2. Nginx第三方模块2.1 echo模块 3. 变量3.1 内置变量3.1.1 示例 3.2 自定义变量3.2.1 自定义访问日志3.2.2 自定义json 格式日志 3.4 Nginx压缩功能 4. HTTPS4.1 Nginx的HTTPS工作原理4.2 启用功能模块的配置过程 5、自定义图标 1. 网页的状态页 基于…

【网络安全防护】上海道宁与Bitdefender帮助您构建弹性网络并降低安全运营成本

在网络的世界中 风险变得更加常见与复杂 企业需要从网络安全转向网络弹性 复杂的网络攻击已非常普遍 在面临攻击时 企业如何保持业务连续性&#xff1f; Bitdefender GravityZone将 风险分析、安全加固、威胁预防 检测和响应功能相结合 帮助您构建弹性网络 并降低安全…

【UE5】虚幻5教程-如何解决场景远处植被没有阴影

没有阴影的远处植被 下面是解决的方法。 首先打开项目设置 项目设置 点击左侧的渲染 渲染 在框内输入“距离”&#xff0c;并选择生成距离场。 光源内添加“定向光源”&#xff0c;如果已有可以忽略。 点击“directional light"并在下方找到"距离场阴影&qu…

go学习part20(1)反射

283_尚硅谷_反射基本介绍和示意图_哔哩哔哩_bilibili 1.介绍 1&#xff09;基本数据类型的类型和类别一致&#xff0c;但是结构体等不一样。 2)反射的例子&#xff08;桥连接&#xff0c;序列化&#xff09; 序列化指定tag&#xff0c;会反射生成tag字符串 3&#xff09;refl…

部署java程序的服务器cpu过高如何排查和解决

1.top命令找到占用CPU高的Java进程PID 2.根据进程ID找到占用CPU高的线程 ps -mp pid -o THREAD,tid | sort -r ps -mp 124682 -o THREAD,tid | sort -r 3.将指定的线程ID输出为16进制格式 printf “%x\n” tid printf "%x\n" 6384 18f0 4.jstack pid |…

一句话画出动漫效果

链接&#xff1a; AI Comic Factory - a Hugging Face Space by jbilcke-hfDiscover amazing ML apps made by the communityhttps://huggingface.co/spaces/jbilcke-hf/ai-comic-factory 选择类型&#xff1a; Japanese 输入提示词&#xff1a; beauty and school love st…

pyechart笔记:opts.AxisOpts

定制化图表的轴线&#xff08;x轴和y轴&#xff09;的样式和设置 0 不设置坐标轴 c1(Bar().add_xaxis([力量,智力,敏捷]).add_yaxis(全能骑士,# 系列名称&#xff0c;用于 tooltip 的显示&#xff0c;legend 的图例筛选。[429,321,296],#系列数据).add_yaxis(猴子,[352,236,4…

开源微服务如何选型?Spring Cloud、Dubbo、gRPC、Istio 详细对比

作者&#xff1a;刘军 不论您是一名开发者、架构师、CTO&#xff0c; 如果您曾深度参与在微服务开发中&#xff0c;那么相信您一定有过开源微服务框架或体系选型的疑问&#xff1a;Apache Dubbo、Spring Cloud、gRPC 以及 Service Mesh 体系产品如 Istio&#xff0c;到底应该选…

【taro react】(游戏) ---- 贪吃蛇

1. 预览 2. 实现思路 实现食物类&#xff0c;食物坐标和刷新食物的位置&#xff0c;以及获取食物的坐标点&#xff1b;实现计分面板类&#xff0c;实现吃食物每次的计分以及积累一定程度的等级&#xff0c;实现等级和分数的增加&#xff1b;实现蛇类&#xff0c;蛇类分为蛇头和…

【状态估计】基于UKF法、AUKF法、EUKF法电力系统三相状态估计研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

IDEA 出现问题:.gitgnore忽略文件失效解决方案

❤️作者主页&#xff1a;小虚竹 ❤️作者简介&#xff1a;大家好,我是小虚竹。Java领域优质创作者&#x1f3c6;&#xff0c;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;掘金年度人气作者&#x1f3c6; ❤️技术活&#xff0c;该赏 ❤️点赞…

开始MySQL之路——MySQL安装和卸载

MySQL的介绍 MySQL数据库管理系统由瑞典的DataKonsultAB公司研发&#xff0c;该公司被Sun公司收购&#xff0c;现在Sun公司又被Oracle公司收购&#xff0c;因此MySQL目前属于Oracle旗下产品。 MySQL所使用的SQL语言是用于访问数据库的最常用标准化语言。MySQL软件采用了双授权…

Docsify + Gitalk详细配置过程讲解

&#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是Zeeland&#xff0c;开源建设者与全栈领域优质创作者。&#x1f4dd; CSDN主页&#xff1a;Zeeland&#x1f525;&#x1f4e3; 我的博客&#xff1a;Zeeland&#x1f4da; Github主页: Undertone0809 (Zeeland)&…

Python爬虫(十七)_糗事百科案例

糗事百科实例 爬取糗事百科段子&#xff0c;假设页面的URL是: http://www.qiushibaike.com/8hr/page/1 要求&#xff1a; 使用requests获取页面信息&#xff0c;用XPath/re做数据提取获取每个帖子里的用户头像连接、用户姓名、段子内容、点赞次数和评论次数保存到json文件内…

什么是HTTPS协议?与HTTP协议区别?

一、协议科普 HTTP协议&#xff08;超文本传输协议&#xff09;是一种用于在计算机网络上传输超文本的应用层协议。它是一种客户端-服务器协议&#xff0c;允许客户端通过Web浏览器等方式向服务器发送请求&#xff0c;服务器则返回响应。HTTP协议是构建万维网&#xff08;WWW&…

详解排序算法(附带Java/Python/Js源码)

冒泡算法 依次比较两个相邻的子元素&#xff0c;如果他们的顺序错误就把他们交换过来&#xff0c;重复地进行此过程直到没有相邻元素需要交换&#xff0c;即完成整个冒泡&#xff0c;时间复杂度。 比较相邻的元素。如果第一个比第二个大&#xff0c;就交换它们两个&#xff1b;…

Leetcode107. 二叉树的层序遍历 II

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&#xff09; 输入&#xff1a;root [3,9…

咸虾米之一些快捷方式的操作,一行方块的左右滑动,方块在一区域内的任意移动

由于本着只学习微信小程序的目的&#xff0c;上面的几篇博文都是跟着黑马程序的课程走的&#xff01;后面的就讲解uni-app的实验呢&#xff01;一个人的精力是有限的&#xff0c;于是换了们课程继续深造微信小程序&#xff01;&#xff01;&#xff01; 以下是在 .wxml中的一些…