vector简单模拟

1.二维vector

下图可以看到vector<int>指向的是几个int型的,而vector<vector<int>>则指向的是几个vector<int>型的内容,而它们又指向几个int型的内容,三维就重复就可以理解。

 例题:

可以得到的规律中间(假设索引为2)的等于上面索引为2和1的相加,而且第一行和第二行不用动都是1,且每一行的头尾也不动是1。

先构建二维vector,然后以i+1(列的增加)来递增,然后用俩重循环来给中间赋值。

 

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> v(numRows);
        for(size_t i=0;i<numRows;i++)
        {
            v[i].resize(i+1,1);
        }

        for(int i=0;i<v.size();i++)
        {
            for(int j=1;j<v[i].size()-1;++j)
            {
                v[i][j]=v[i-1][j]+v[i-1][j-1];
            }
        }
        return v;
    }
};

2.代码解析

 1.迭代器实现

用typedef重命名T*为iterator,成员变量是_start,_finish,_end_of_storage,所以begin()获取_start指向的位置,end()获取_finish指向的位置,后面俩个在函数后面+const的是指里面的内容都是只读不可以修改。

        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;
		}


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

2. vector的大小容量以及判断空

vector的size可以通过首尾指针相减得到的距离值获取,容量则就使用原本容量空间-首的位置,判断是否为空看_start和_finish是否相等。


		size_t size()
		{
			return _finish - _start;
		}

		size_t capacity() const
		{
			return _end_of_storage - _start;
		}

		bool empty()
		{
			return _start == _finish;
		}

3. 容量设置

比较n和capacity的大小,因为我们是只打不小,所以只有大了才指向扩容,要保留原的size,如果不保留原来的size则在_finish=tmp+old_size这里就有问题,因为size就是_finish-_start,而不保留则用的是原来vector的size那么_finish=_finish(前一个的_finish),那么_start指向的是新的vector,而_finish还是指向旧的,所以就不行(迭代器失效问题)。

void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t old_size = size();
				T* tmp = new T[n];
				memcpy(tmp, _start, sizeof(T) * size());
				delete[] _start;

				_start = tmp;
				_finish = tmp + old_size;
				_end_of_storage = tmp + n;
			}
		}

 4.尾插和尾删

在尾插时要判断容量是否足够,不够就扩容,够就在_finish处插入值,然后再把_finish指向插入处的下一个位置,尾删要想判断是否为空,有才能删除,直接把_finish-1就删除了一个数据。

void push_back(const T& x)
		{
			if (_finish == _end_of_storage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*_finish = x;
			++_finish;
		}

		void pop_back()
		{
			assert(!empty());
			--_finish;
		}

 5.在指定位置插入

这里len保存pos-_start是因为下面有reserve函数会改变vector,_start和_finish会去新的vector而pos还在旧的vector,接下来就是挪动数据把pos位置空出来填要插入的数据。

iterator insert(iterator pos, const T& x)
		{
			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;//怕迭代器失效

				reserve(capacity() == 0 ? 4 : 2 * capacity());
				pos = _start + len;
			}

			iterator end = _finish - 1;//因为有一个数据finish+1 但是索引0处才有数据,而finish=1处没有所以访问要-1
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;

			return pos;
		}

6.重载函数

 _start[i]=*(_start+i),获取对应位置的解引用值,下面则是返回常量引用且是只读。

T& operator[](size_t i)
		{
			assert(i < size());

			return _start[i];
		}

		const T& operator[](size_t i) const
		{
			assert(i < size());

			return _start[i];
		}

7.测试函数

先尾插五个数据,然后在位置2插入20,这里用auto p接收pos而不用pos是因为插入后vector跟没插入之前是不一样了,所以pos失效了,可以通过函数返回值来得到位置,进而得到想要结果,输入在insert中有修正,但是pos是在insert函数的形参,而p是在测试函数的形参,这俩是没有关系的,除非实参修正才有用。(如果insert用的是引用也不可以,因为表达式的返回是临时变量具有常性,所以要有const &才行,但是加了const就不能修改pos了,所以不可以)

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);
		
		print_vector(v);

		v.insert(v.begin() + 2, 30);
		print_vector(v);

		int x;
		cin >> x;

		auto p = find(v.begin(), v.end(), x);
		if (p != v.end())
		{
			// insert以后p就是失效,不要直接访问,要访问就要更新这个失效的迭代器的值
			//v.insert(p, 40);
			//(*p) *= 10;

			p = v.insert(p, 40);
			(*(p + 1)) *= 10;
		}
		print_vector(v);
	}

 find函数解释:

 

std::find 函数的原型定义在 C++ 标准库的 &lt;algorithm&gt; 头文件中。以下是其基本原型:
template&lt;class ForwardIt, class T&gt;
ForwardIt find(ForwardIt first, ForwardIt last, const T&amp; value);

参数说明

1.ForwardIt first:范围的开始迭代器,表示要搜索的序列的第一个元素的迭代器。
2.ForwardIt last:范围的结束迭代器,表示要搜索的序列的最后一个元素后面的迭代器(不包含该位置)。
3.const T&amp; value:要查找的值,可以是任何类型(例如基本数据类型、用户定义类型等)。

返回值

4.返回一个迭代器,指向找到的第一个匹配元素。如果在指定范围内没有找到该元素,则返回 last 迭代器。

使用示例
这里是一个简单的示例,展示如何使用 std::find 函数:
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;

int main() {
    std::vector&lt;int&gt; v = {1, 2, 3, 4, 5}; // 创建一个整数类型的vector
    int x = 3; // 要查找的值

    // 使用 std::find 查找值 x
    auto p = std::find(v.begin(), v.end(), x);

    // 检查查找结果
    if (p != v.end()) {
        std::cout &lt;&lt; "Found " &lt;&lt; x &lt;&lt; " at index " &lt;&lt; std::distance(v.begin(), p) &lt;&lt; std::endl;
    } else {
        std::cout &lt;&lt; x &lt;&lt; " not found in the vector." &lt;&lt; std::endl;
    }

    return 0;
}

总结
std::find 是一种非常方便的查找算法,能够简化在容器中查找元素的操作,并且通过使用模板支持各种数据类型。

 

3.总代码 

vector.h

#pragma once
#include<iostream>
#include<assert.h>

namespace zym
{
	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;
		}
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t old_size = size();
				T* tmp = new T[n];
				memcpy(tmp, _start, sizeof(T) * size());
				delete[] _start;

				_start = tmp;
				_finish = tmp + old_size;
				_end_of_storage = tmp + n;
			}
		}

		size_t size()
		{
			return _finish - _start;
		}

		size_t capacity() const
		{
			return _end_of_storage - _start;
		}

		bool empty()
		{
			return _start == _finish;
		}

		void push_back(const T& x)
		{
			if (_finish == _end_of_storage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*_finish = x;
			++_finish;
		}

		void pop_back()
		{
			assert(!empty());
			--_finish;
		}
		iterator insert(iterator pos, const T& x)
		{
			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;//怕迭代器失效

				reserve(capacity() == 0 ? 4 : 2 * capacity());
				pos = _start + len;
			}

			iterator end = _finish - 1;//因为有一个数据finish+1 但是索引0处才有数据,而finish=1处没有所以访问要-1
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;

			return pos;
		}
		T& operator[](size_t i)
		{
			assert(i < size());

			return _start[i];
		}

		const T& operator[](size_t i) const
		{
			assert(i < size());

			return _start[i];
		}

		


	private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _end_of_storage = nullptr;
	};

	template<class T>
	void print_vector(const vector<T>& v)
	{
		auto it = v.begin();
		while (it != v.end())
		{
			cout << *it << "";
			++it;
		}

		cout << endl;

		for (auto e : v)
		{
			cout << e << "";
		}
		cout << 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);
		
		print_vector(v);

		v.insert(v.begin() + 2, 30);
		print_vector(v);

		int x;
		cin >> x;

		auto p = find(v.begin(), v.end(), x);
		if (p != v.end())
		{
			// insert以后p就是失效,不要直接访问,要访问就要更新这个失效的迭代器的值
			//v.insert(p, 40);
			//(*p) *= 10;

			p = v.insert(p, 40);
			(*(p + 1)) *= 10;
		}
		print_vector(v);
	}
}

 

test.cpp


#include<iostream>

using namespace std;
#include"vector.h"


int main()
{
	zym::test_vector2();
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java—继承性与多态性

目录 一、this关键字 1. 理解this 2. this练习 二、继承性 2.1 继承性的理解 2.1.1 多层继承 2.2 继承性的使用练习 2.2.1 练习1 2.2.2 练习2 2.3 方法的重写 2.4 super关键字 2.4.1 子类对象实例化 三、多态性 3.1 多态性的理解 3.2 向下转型与多态练习 四、Ob…

ArmSoM-Sige7 成为首款支持 openSUSE 的 RK3588 设备

随着嵌入式系统和开源软件的不断发展&#xff0c;越来越多的开发者和爱好者对高性能的开发板及其操作系统支持寄予厚望。在这一背景下&#xff0c;ArmSoM-Sige7 凭借其强大的硬件性能和广泛的软件兼容性&#xff0c;成为了市场的关注焦点。令人兴奋的是&#xff0c;ArmSoM-Sige…

linux 配置ssh免密登录

一、 cd /root/.ssh/ #不存在就创建mkdir /root/.ssh ssh-keygen #连续按4个回车 ll二、将公钥发送到目标服务器下 #公钥上传到目标服务器 ssh-copy-id root192.168.31.142 #回车完也是要输入密码的 #测试一下免密登录&#xff1a; ssh root192.168.31.142 成功

spring如何解决bean循环依赖的问题

1、概述 spring中&#xff0c;存在A依赖B&#xff0c;同时B又依赖A的情况&#xff0c;这种情况下&#xff0c;spring如何进行bean初始化呢&#xff1f; Service public class A {Autowiredprivate B b; }Service public class B {Autowiredprivate A a; } 本文来解释这个问题…

Mindustry像素工厂服务器开服教程

1、购买后登录服务器&#xff08;百度莱卡云游戏面板&#xff09; 进入控制面板后会出现正在安装的界面&#xff0c;大约5分钟左右就能安装完成 2、等待服务器运行起来 等待正常运行时间的表变成灰色之后就可以连接游戏了 3、连接游戏 先复制服务器的地址&#xff0c;单击地址…

【fisco学习记录2】多群组搭建

说明 文档参考&#xff1a; 多群组部署 — FISCO BCOS 2.0 v2.11.0 文档 (fisco-bcos-documentation.readthedocs.io) 多群组搭建之前&#xff0c;先暂停之前的单群组&#xff0c;并删除&#xff1a; cd fisco bash nodes/127.0.0.1/stop_all.sh rm -rf nodes/ 实现图&…

又一款国产自动化测试平台,开源了!

“时间就是金钱&#xff0c;效率就是生命”&#xff0c;在当下的社会里不仅我们的生活节奏变得越来越快&#xff0c;软件研发上线的节奏也是如此。在如此快节奏的软件开发环境中&#xff0c;高质量的软件测试变得尤为重要。 为了提高测试的效率和质量&#xff0c;建设一个强大…

小北的技术博客:探索华为昇腾CANN训练营与AI技术创新——Ascend C算子开发能力认证考试(初级)

前言 哈喽哈喽友友们,这里是zyll~(小北)智慧龙阁的创始人及核心技术开发者。在技术的广阔天地里,我专注于大数据与全栈开发,并致力于成为这一领域的新锐力量。通过智慧龙阁这个平台,我期望能与大家分享我的技术心得,共同探索技术的无限可能。 Ascend C编程:小北的技术…

【大数据技术基础 | 实验二】Linux基础:常用基本命令和文件操作

文章目录 一、实验目的二、实验要求三、实验环境四、常用基本命令1、验证cd和pwd命令2、验证ls命令3、验证mkdir命令4、验证cp、mv和rm命令 五、Linux文件操作1、验证touch命令2、验证cat命令3、验证more命令 六、实验心得 一、实验目的 学会linux常用命令(cd,ls,pwd,mkdir,rm…

元器件行业常用软件推荐-加速度JSUDO

元器件行业中&#xff0c;工程师们会使用多种软件来辅助设计、仿真、布局、布线和验证等工作。以下是一些推荐的软件&#xff0c;它们在电子设计自动化&#xff08;EDA&#xff09;和集成电路&#xff08;IC&#xff09;设计领域中被广泛使用&#xff1a; Altium Designer&…

创建包含可导入浏览器信任的SSL自签名证书

问题&#xff1a;现在的三大浏览器&#xff0c;chrome、edge、firefox 一般都默认启用https检查&#xff0c;这就要求我们自建的局域网内的网址和其他诸如nextcloud、photoprism、tiddlywiki等应用也必须要有证书。解决方法是使用openssl自己生成一个。由此则会再衍生出一个问题…

计算机视觉之YOLO算法基本原理和应用场景

YOLO算法基本原理 整体流程 YOLO 将目标检测问题转化为一个回归问题。它将输入图像划分成多个网格单元&#xff0c;每个网格单元负责预测中心点落在该网格内的目标。对于每个网格单元&#xff0c;YOLO 预测多个边界框以及这些边界框中包含目标的类别概率。边界框通常由中心点坐…

(vue)a-upload上传文件后将结果展示图片

&#xff08;vue&#xff09;a-upload上传文件后将结果展示图片 亲测有效 项目背景&#xff1a;油气项目上传数字岩心图片 接口返回 控制台打印的info: 代码 <a-uploadname"file"list-type"picture-card"class"avatar-uploader":show-u…

LabVIEW如何实现高精度定时器

在LabVIEW中实现高精度定时器通常需要考虑以下几个方面&#xff1a;定时器的精度要求、操作系统的调度机制、硬件资源&#xff08;如计时器、触发器&#xff09;等。以下是几种常见的实现方式&#xff1a; ​ 1. 使用 Wait(ms) 或 Wait Until Next ms Multiple VI 这两个函数…

Docker-compose 单节点管理、consul 注册中心、registrator、template

consul是一个基于分布式的服务发现和配置管理工具。它具有快速构建分布式架构&#xff0c;提供服务发现和服务注册功能。consul职能&#xff1a;1、自动发现、注册&#xff1b;2、自动配置&#xff1b;3、自动更新 服务发现&#xff1a;自动检查网络中的服务&#xff08;如数据…

101、QT摄像头录制视频问题

视频和音频录制类QMediaRecorder QMediaRecorder 通过摄像头和音频输入设备进行录像。 注意: 使用Qt多媒体模块的摄像头相关类无法在Windows平台上进行视频录制&#xff0c;只能进行静态图片抓取但是在Linux平台上可以实现静态图片抓取和视频录制。 Qt多媒体模块的功能实现是依…

李沐团队发布Higgs-Llama-3-70B,角色扮演专用模型

前言 近年来&#xff0c;大语言模型&#xff08;LLM&#xff09;在各个领域都展现出强大的能力&#xff0c;尤其是其在对话、写作、代码生成等方面的应用越来越广泛。然而&#xff0c;想要让 LLM 真正地融入人类社会&#xff0c;扮演各种角色&#xff0c;还需要具备更强大的角…

Qt媒体播放器实现

本文介绍Qt媒体播放器实现。 Qt应用程序有时会涉及到视频文件的播放&#xff0c;Qt提供了QVideoWidget类实现视频和音频的播放&#xff0c;本文基于QVideoWidget类实现一个简单的媒体播放器。 1.自定义类&#xff08;基于QVideoWidget类&#xff09; 由于Qt并未提供专门的控…

免费绘图软件全解析:让你的创意工作更加高效

在数字化时代&#xff0c;绘图软件已成为我们生活中不可或缺的一部分&#xff0c;无论是业余爱好者还是专业设计师。幸运的是&#xff0c;市面上有许多免费且功能强大的绘图软件可供选择。以下是我们为您精选的8款免费绘图软件&#xff0c;每一款都是精心挑选的&#xff0c;值得…

idea2024启动Java项目报Error running CloudPlApplication. Command line is too long.

idea2024启动Java项目报Error running CloudPlApplication. Command line is too long. 解决方案&#xff1a; 1、打开Edit Configurations 2、点击Modify options设置&#xff0c;勾选Shorten command line 3、在Edit Configurations界面下方新增的Shorten command line选项中…