vector的模拟实现01
文章目录
- vector的模拟实现
- 构造函数
- 析构函数
- 迭代器
- 容量
- size
- capacity
- reverse
- 遍历
- 下标+[]
- 修改
- push_back
- pop_back
- insert
- 结语
我们大家有又见面了,给生活加点</font color =red>impetus!!开启今天的编程之路
今天我们来学习vector。了解一些基本的接口已经迭代器失效问题!!
作者:٩( ‘ω’ )و260
我的专栏:C++初阶,数据结构初阶,题海探骊,c语言
感谢点赞,关注!!
vector的模拟实现
在 C++ 里,std::vector 属于标准模板库(STL)中的容器,它可看作是动态数组。话多多说,直接进入模拟实现。
首先我们先要明白,vectoe底层是数组,如果我们数组中存储的是字符类型,那还要string类干嘛:
1:string后面默认有\0,vector没有
2:接口有较大差异,比如vector中其实没有find函数,只能使用算法库中的函数
其次就是需要定义vector的结构,也许你会认为可以使用顺序表定义的结构,但是在这里,我们为了更加接触底层,在vector的源代码中,他的成员函数是这样定义的:总共有三个,分别为迭代器,名称为:_start,_finish,_end_of_storage。分别代表的是有效位置的第一个元素,有效位置的最后一个元素,有效空间的最后一个位置
我们来看下面的定义:
class vector{
pubilc:
private:iterator _start;iterator _finish;iterator _end_of_storage;
};
其实这样还是会有一点小瑕疵,编译器怎么知道iterator是什么东西吗?
而且,vector的底层是数组,那么数组应该是可以存储各式各样的数据类型,包括整形,浮点数,自定义类型等等,我们再来加以修改一下:
template<class T>
class vector{
pubilc:typedef T* iterator;//定义普通迭代器typedef const T* const_iterator;//定义const迭代器
private:iterator _start;iterator _finish;iterator _end_of_storage;
}
作用:指向各种数据的迭代器。
因为vector的底层是数组,所以这里的迭代器就可以理解为数组的指针,本质上是因为数组空间是连续的。在这里,我们需要重点学习迭代器失效!!
这里的迭代器的typedef一定要定义在public中,这样外面才能使用。
随后我想补充自己总结的知识点:
1:模版可以做声明和定义分离,但是不要分离到两个文件,否则会发生链接错误
2:利用模版传参一般是传引用,因为是数组,值传递的时候调用拷贝构造,目的是防止深拷贝
3:注意,只有先声明模版,函数才能够传递模版参数,例如
//template<class T>
//void Print(const Mrzeng::vector<T>&res){}
构造函数
在这里我们主要实现是三种构造函数,第一种是无参构造,第二种是有参构造,第三种是利用其他类来进行构造
先来看第一种
因为是无参的构造函数,所以我们构造函数的时候必须要去初始化列表中初始化,但是由于这些都是迭代器可以理解为指针,所以我们直接将三者的初始化为空指针:
vector
:_start(nullptr),_finish(nullptr),_end_of_storage(nullptr)
{}
接下来我们来完成有参的初始化,但是这里的结果是数组中的数据全部都是相同的,因为这种构造就是用n个val值来初始化vector实例化的对象:
直接来看代码:
vector(size_t n,const T& val=T())//匿名对象
{assert(n>0);reverse(n);for(size_t i=0;i<n;i++){ push_back(val);}
}
虽然说我们还没有实现迭代器以后push_back,但是这个大致思路确实是如此。
首先第一句代码使用了匿名对象:因为外部传给vector的值并不确定,所以vector中有可能能够存储各式各样的值,我们这里只能够使用匿名对象。
匿名对象首先会调用的构造函数,去构造一个自定义类型之后就会传递给vector,那么,有的同学会问,那内置类型怎么办呢?难道内置类型使用匿名对象时会升级为自定义类型?
答案确实是如此,接下来利用代码验证:
接下来实现第三种,使用另一个模版来构造vector,鉴于我们对于后面还没学习,这里主要讲解用法,来看代码:
vector(initializer_list<T> il)
{reverse(il.size());for(auto& e:il){push_back(e);}
}
initializer_list是另一类,在这里初始化的时候可以使用任何数据来进行初始化,比如:
vector<int> v1{1,2,3,4,5};
在这里的原理是什么呢?
利用initializer_list初始化时自动开空间,自动生成首尾迭代器,这也是为什么我我没有显示写begin(),end(),但是也能够使用范围for。注意范围for的本质就是迭代器
析构函数
析构函数简单,只需要释放开辟的空间即可,来看下列代码:
~vector()
{if(_start){delete[]_start;_start=_finish=_end_of_storage=nullptr;}
}
这里只需要判断是否需要析构即可,因为一开始无参初始化三个成员变量都是空,再来析构的话就显得画蛇添足了!!
迭代器
这里实现开始与结束的迭代器,与string类相差无几,直接来看代码:
iterator begin()
{return _start;
}
iterator end()
{return _finish;
}
const_itreator begin()const
{ return _start;
}
const_iterator end()const
{return _finish;
}
在迭代器这里有一个细节:
迭代器是左闭右开的类型,类似于[begin(),end()),末尾迭代器并不是包含在内的元素,这里需要记忆
容量
size
size其实就是有效位置的最后迭代器减上有效位置的起始迭代器即可:
size_t size()const
{return _finish-_start;
}
可以理解为指针:两个指针相减的值就是其中相邻元素的个数,前提是指向同一块空间
capacity
capacity就是容量的最后位置迭代器减上有效位置起始迭代器:
size_t capacity()const
{return _end_of_capacity-_start;
}
可以理解为指针:两个指针相减的值就是其中相邻元素的个数,前提是指向同一块空间
reverse
需要判断什么时候需要扩容,扩容之后又要做什么,代码是否有错误?而在扩容之中我们又需要干什么?
来看下列代码:
void reverse(size_t n)
{if(n>_end_of_storage){T*tmp=new T[n];memcpy(tmp,_start,size()*sizeof(T));//注意memcpy的单位是字节delete[]_start;_start=tmp;//修改成员变量_finish=tmp+size();_end_of_capacity=tmp+n;}
}
这里在_finish和_end_of_storage修改成员变量的时候主要是为了标记这个迭代器是在哪个vector之中的!!
那么我们上面还有没有可以优化的地方呢?上面的代码有没有问题呢?我们来看一下:
首先我们看一下倒数第二行的size,计算是通过_finish-_start实现的,但是我们发现,在求size之前我们就已经对_start进行了变化,此时_finish指向旧的已经被销毁的空间,_start指向新空间的起始位置,此时代码肯定报错:
再来看这张图理解,所以如果按照这个代码扩容的话,_finish的结果会一直是0。
最终代码:
void reverse(size_t n)
{if(n>_end_of_storage){size_t old_size=size();//存储下来这个偏移量T*tmp=new T[n];if(_start)//如果被拷贝数据此时不是空的话,我再来进行操作,否则就不需要操作了{memcpy(tmp,_start,old_size*sizeof(T));delete[]_start;}_start=tmp;//修改成员变量_finish=tmp+old+size();_end_of_capacity=tmp+n;}
}
遍历
下标+[]
此时与string相差无几,直接来看代码即可:
T& operator[](size_t pos)
{assert(pos < size());return _start[pos];
}
修改
push_back
尾插,首先我们需要先判断是否需要扩容,随后再来进行尾插,最后再对成员变量进行修改:
来看代码:
void push_back(const T&x)
{if(_finish==_end_of_storage){size_t newcapacity=_end_of_storage==0?4:2*capacity();reverse(newcapacity);}*_finish=x;_finish++;
}
pop_back
对尾部进行删除,删除之后修改成员变量
void pop_back()
{_finish--;
}
直接让有效元素减一个就可以了
insert
我们需要在指定位置进行插入操作,首先需要先检查是否需要扩容,随后再来移动元素,最后再插入数据以及修改成员变量。
来看代码:
void insert(iterator pos,const T&x)
{if(_finish==_end_of_storage){size_t newcapacity=_end_of_storage==0?4:2*capacity();reverse(newcapacity);}iterator it=_finish-1;while(it>=pos){*(it+1)=*it;it--;}*pos=x;_finish++;
}
这样的代码看起来是ok的,但是如果我们去检验,我们会发现一个问题,此时我们会发现我们一直无法退出循环,那这个是什么原因呢?迭代器失效–原因是野指针
我们如果发生了扩容,就会导致旧空间销毁,但是最开始pos迭代器肯定是指向旧空间的,开辟新空间之后pos迭代器变成就是野指针了,所以我们应该及时对pos迭代器进行修改
所以我们这里应该改为:
if(_finish==_end_of_storage){int len=pos-_start;//记录下偏移量size_t newcapacity=_end_of_storage==0?4:2*capacity();reverse(newcapacity);//利用偏移量找到新的pos迭代器pos=_start+len;//前面加一个_start主要是为了标记新的数组的偏移量}
来看下面图解:
这里还有一个细节:
如果我们在外面设置了pos指针,插入数据之后一定不要再去使用这个迭代器,因为我不知道是否会产生扩容,不知道这个迭代器是否会被更新,因为我这里是使用的传值调用,里面的操作不会影响外面,里面这个迭代器经历了什么我是一点都不知道的。
那你可能会说,那我们转引用不就好了吗?但是如果是一个迭代器再来进行算术加减法,就会产生一个临时对象记录这个结果,传过去临时对象,不加const的话又是一个权限放大问题,所以我们必须加上const,但是加上const我的pos位置的数据就不能再修改了!!
所以:为了方便,不要在使用调用insert实参为迭代器的变量了!!
示例代码:
int x = 2;cin >> x;auto pos = find(v.begin(), v.end(), x);if (p != v.end()){v.insert(pos, x * 10);// insert以后pos不能使用,pos可能失效,不要访问这个迭代器// cout << *pos << endl;}
find是算法库中的函数,如果找到对应位置数值为x的位置,就会放回这个位置的迭代器,,否则会返回last位置的迭代器,代表没有找到。
结语
感谢大家阅读我的博客,不足之处欢迎与我交流讨论。
时人不识凌云木,直待凌云始道高!!加油!!
相关文章:
vector的模拟实现01
文章目录 vector的模拟实现构造函数析构函数迭代器容量sizecapacityreverse 遍历下标[] 修改push_backpop_backinsert 结语 我们大家有又见面了,给生活加点</font color red>impetus!!开启今天的编程之路 今天我们来学习vector。了解一…...
信息学奥赛一本通 1609:【例 4】Cats Transport | 洛谷 CF311B Cats Transport
【题目链接】 ybt 1609:【例 4】Cats Transport 洛谷 CF311B Cats Transport 【题目考点】 1. 动态规划:斜率优化动规 【解题思路】 解法1:设a点的前缀和 输入的 d d d序列是从 d 2 d_2 d2到 d n d_n dn,共n-1个数字。人…...
shared_ptr和 weak_ptr的详细介绍
关于 shared_ptr 和 weak_ptr 的详细介绍及使用示例: 1. shared_ptr(共享所有权智能指针) 核心特性 引用计数:记录当前有多少个 shared_ptr 共享同一个对象。自动释放:当引用计数归零时,自动释放对象内存…...
electron打包vue2项目流程
1,安装一个node vue2 的项目 2,安装electron: npm install electron -g//如果安装还是 特比慢 或 不想安装cnpn 淘宝镜像查看是否安装成功:electron -v 3,进入到项目目录:cd electron-demo 进入项目目录…...
Baklib驱动企业知识管理数字化转型
Baklib驱动知识资产激活 在信息碎片化与数据爆炸的产业环境下,企业知识中台正成为重构组织智慧的核心枢纽。Baklib通过构建全生命周期知识管理模型,将分散于邮件、文档及协作系统的非结构化数据转化为可检索、可分析的标准化资产。其内置的智能分类引擎…...
Elasticsearch 高级
Elasticsearch 高级 建议阅读顺序: Elasticsearch 入门Elasticsearch 搜索Elasticsearch 搜索高级Elasticsearch高级(本文) 1. nested 类型 1.1 介绍 Elasticsearch 中的 nested 类型允许你在文档内存储复杂的数据结构,比如一个…...
1--当「穷举」成为艺术:CTF暴力破解漏洞技术从入门到入刑指南(知识点讲解版)
当「穷举」成为艺术:CTF暴力破解漏洞技术从入门到入刑指南 引言:论暴力破解的哲学意义 “世界上本没有漏洞,密码设得简单了,便成了漏洞。” —— 鲁迅(并没有说过) 想象你是个不会撬锁的小偷,面…...
jdk 支持路线图
https://www.oracle.com/java/technologies/java-se-support-roadmap.html 按照路线图得知,在2025.09 发布openjdk 25,是一个LTS版本。...
VsCode启用右括号自动跳过(自动重写) - 自录制gif演示
VsCode启用右括号自动跳过(自动重写) - 自录制gif演示 前言 不知道大家在编程时候的按键习惯是怎样的。输入完左括号后编辑器一般会自动补全右括号,输入完左括号的内容后,是按→跳过右括号还是按)跳过右括号呢? for (int i 0; i < a.s…...
Android设计模式之模板方法模式
一、定义: 定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 二、结构: AbstractClass抽象类:定义算法的骨架,包含模板方法和若干…...
纯个人整理,蓝桥杯使用的算法模板day1(dfs、bfs)
算法索引 dfs(深度优先搜索)bfs(广度优先搜索)迷宫树结构 dfs(深度优先搜索) 功能: 适合搜索所有的解 代码模板: class Solution{public void dfs(int[][] graph, int i, int j){i…...
【第34节】windows原理:PE文件的导出表和导入表
目录 一、导出表 1.1 导出表概述 1.2 说明与使用 二、导入表 2.1 导入表概述 2.2 说明与使用 一、导出表 1.1 导出表概述 (1)导出行为和导出表用途:PE文件能把自身的函数、变量或者类,提供给其他PE文件使用,这…...
Spring Boot事务管理详解(附银行转账案例)
一、事务基础概念 事务的ACID特性: 原子性(Atomicity):操作要么全部成功,要么全部失败一致性(Consistency):数据在事务前后保持合法状态隔离性(Isolation)&…...
(头歌作业—python)3.2 个人所得税计算器(project)
第1关:个人所得税计算器 任务描述 本关任务:编写一个个人所得税计算器的小程序。 相关知识 个人所得税缴纳标准 2018 年 10 月 1 日以前,个税免征额为 3500 元/月,调整后,个税免征额为 5000 元/月, 7 级超…...
在一个scss文件中定义变量,在另一个scss文件中使用
_variables.scss文件 : $line-gradient-init-color: linear-gradient(90deg, #8057ff 0%, #936bff 50%, #b892ff 100%); $line-gradient-hover-color: linear-gradient(90deg, #936bff 0%, #b892ff 50%, #f781ce 100%); $line-gradient-active-color: linear-gradient(90deg, …...
【计网】网络交换技术之电路交换(复习自用)
复习自用的,处理得比较草率,复习的同学或者想看基础的同学可以看看,大佬的话可以不用浪费时间在我的水文上了 1.电路交换定义 电路交换是一种通信方法,在通信开始之前,源和目的地之间建立一条专用的物理路径…...
MacOS 安装open webui
open-webui 不是一个 Python 包,所以 pip install open-webui 会失败。它是一个独立的 Web UI 应用,通常通过 Docker 或 手动构建 来运行。 如何正确安装 Open WebUI? 你可以选择 Docker 方式(推荐)或 手动安装。 方法…...
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加行拖拽排序功能示例9,TableView16_09 嵌套表格拖拽排序
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加行拖拽排序功能示例9,TableView16_09 嵌…...
开启ipv6与关闭的区别
在运行P2P CDN时,开启IPv6与关闭IPv6存在以下核心区别,需从技术、合规、运营等维度综合评估: 一、性能与效率 开启IPv6的优势 更大地址空间:IPv6支持海量设备接入,解决IPv4地址枯竭问题,便于P2P CDN节点扩…...
Redis + Caffeine多级缓存电商场景深度解析
Redis Caffeine多级缓存 Redis Caffeine多级缓存电商场景深度解析一、实施目的二、具体实施2.1 架构设计2.2 组件配置2.3 核心代码实现 三、实施效果3.1 性能指标对比3.2 业务指标改善3.3 系统稳定性 四、关键策略4.1 缓存预热4.2 一致性保障4.3 监控配置Prometheus监控指标 …...
Leecode Hot50
文章目录 矩阵Solution73. 矩阵置零Solution54. 螺旋矩阵Solution48. 旋转图像Solution240. 搜索二维矩阵 II二叉树二叉树的四种遍历结果Solution94. 二叉树的中序遍历Solution104. 二叉树的最大深度Solution226. 翻转二叉树Solution101. 对称二叉树Solution543. 二叉树的直径S…...
解决 Gradle 构建错误:Could not get unknown property ‘withoutJclOverSlf4J’
解决 Gradle 构建错误:Could not get unknown property ‘withoutJclOverSlf4J’ 在构建 Spring 源码或其他基于 Gradle 的项目时,可能会遇到如下错误: Could not get unknown property withoutJclOverSlf4J for object of type org.gradle…...
C++ 初阶总复习 (16~30)
C 初阶总复习 (16~30) 目的16. 2009. volatile关键字的作用17. 2010.什么是多态 简单介绍下C的多态18. 2011. 什么是虚函数 介绍下C中虚函数的原理19. 2012 构造函数可以是虚函数嘛20. 2013.析构函数一定要是虚函数嘛?21. 2015. 什么是C中的虚…...
TDengine 中的异常恢复
简介 本章主要介绍在 TDengine 执行命令过程中发生异常,如何手工终于执行的任务。可以终止连接,线上查询及终止事务。 如果一个事务 在一个复杂的应用场景中,连接和查询任务等有可能进入一种错误状态或者耗时过长迟迟无法结束,…...
二层框架组合实验
实验要求: 1,内网IP地址使用172.16.0.0/16分配 2,SW1和sw2之间互为备份 3,VRRP/STP/VLAN/Eth-trunk均使用 4,所有PC均通过DHCP获取IP地址 5,ISP只能配置IP地址 6,所有电脑可以正常访问ISP路由器环回 实验思路顺序: 创建vlan eth-trunk 划分v…...
IP综合实验
1.配置eth-trunk进行绑定 [LSW1]interface Eth-Trunk 0 [LSW1-Eth-Trunk0]q [LSW1]interface g0/0/2 [LSW1-GigabitEthernet0/0/2]eth-trunk 0 [LSW1-GigabitEthernet0/0/2]int g0/0/3 [LSW1-GigabitEthernet0/0/3]eth-trunk 0 [LSW1-GigabitEthernet0/0/3]display et…...
2025年信息系统与未来教育国际学术会议(ISFE 2025)
基本信息 官网:www.icedcs.net 时间:2025年4月18-20日 地点:中国-深圳 简介 2025年信息系统与未来教育国际学术会议(ISFE 2025)作为第二届粤港澳大湾区教育数字化与计算机科学国际学术会议(EDCS 2025&…...
nacos 外置mysql数据库操作(docker 环境)
目录 一、外置mysql数据库原因: 二、数据库准备工作 三、构建nacos容器 四、效果展示 一、外置mysql数据库原因: 想知道nacos如何外置mysql数据库之前,我们首先要知道为什么要外置mysql数据库,或者说这样做有什么优点和好处&am…...
Windows 10 ARM64平台MFC串口程序开发
Windows 10 IoT ARM64平台除了支持新的UWP框架,也兼容支持老框架MFC。使得用户在Windows 10 IoT下可以对原MFC工程进行功能升级,不用在新框架下重写整个工程。熟悉MFC开发的工程师也可以在Windows 10 IoT平台下继续使用MFC进行开发。 本文展示MFC串口程序…...
怎么使用pm2启动和暂停后端程序(后端架构nodejs+koa)
首先查看自己的pm2进程 pm2 list 或者 pm2 status 如果什么进程都没有,但是你确实有后端程序运行在服务器上,使用以下查看pm2程序的启动用户 ps aux | grep pm2就可以看到具体的用户和进行的信息 接着转换到你要操作的pm2的进程用户下 sudo su - …...
AI人工智能-Jupyter NotbookPycharm:Py开发
安装 命令: pip install jupyter 启动 命令: jupyter notebook 启动成功后,下面网址会默认自动打开当前用户的根目录。 其实这个页面显示的内容,是我们电脑目录C:\Users\当前用户\下的文件夹 我们平常做实验,希望在…...
uniapp-小程序地图展示
一、当前页面直接获取 <view class"map"><map id"myMap" style"width: 100%; height: 40vh;" :latitude"latitude":longitude"longitude" :markers"markers" :scale"scale" :show-location&qu…...
使用 Python 进行链上数据监控:让区块链数据触手可及
使用 Python 进行链上数据监控:让区块链数据触手可及 区块链技术正以前所未有的速度改变着各行各业,特别是在金融、供应链、物联网和智能合约等领域的应用,已经成为了一种新常态。然而,随着区块链网络的快速扩展和去中心化特性的不断强化,数据的可视化与监控变得愈发重要…...
CentOS 7 磁盘及分区管理笔记
一、查看磁盘信息 1. lsblk 命令 作用:列出系统中所有的块设备(包括磁盘、分区等)及其相关信息,如设备名称、大小、类型等。 命令格式:lsblk 示例: lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sd…...
python基础学习二(列表及字典的使用)
文章目录 列表列表的创建获取列表中的多个元素判断列表中元素是否存在列表元素的添加操作列表元素的删除操作列表元素的修改列表的排序列表生成式 字典字典的创建字典的常规操作字典的常用操作字典的视图操作字典元素的遍历字典的特点字典的生成式 列表 一个对象由id࿰…...
【NLP 50、损失函数 KL散度】
目录 一、定义与公式 1.核心定义 2.数学公式 3.KL散度与交叉熵的关系 二、使用场景 1.生成模型与变分推断 2.知识蒸馏 3.模型评估与优化 4.信息论与编码优化 三、原理与特性 1.信息论视角 2.优化目标 3.局限性 四、代码示例 代码运行流程 核心代码解析 抵达梦想靠的不是狂热…...
macOS Jdk1.8安装(目前主流版本的jdk)
Jdk1.8安装 1、jdk安装包下载链接2、下载安装包(根据自己是什么系统进行下载)3、下载完成之后双击安装包进行安装安装好之后查看查看安装的版本需要查看JDK的安装路径(一般在/Library/Java/JavaVirtualMachines)配置环境变量1、jdk安装包下载链接 jdk8下载链接 https://www.…...
树莓派5智能家居中控:HomeAssistant全配置指南
一、硬件选型与系统架构 1.1 树莓派5的硬件优势 2023年发布的树莓派5采用Broadcom BCM2712处理器(4核Cortex-A76架构),相比前代产品具有三大突破性改进: 接口升级:首次支持PCIe 2.0接口,可扩展万兆网卡或…...
Dubbo(22)如何配置Dubbo的服务提供者?
配置Dubbo的服务提供者是实现分布式服务架构的重要步骤。服务提供者负责将服务注册到注册中心,使得服务消费者可以发现并调用这些服务。下面以一个完整的Spring Boot项目为例,详细介绍如何配置Dubbo的服务提供者。 配置步骤 引入依赖:在项目…...
【通道注意力机制】【SENet】Squeeze-and-Excitation Networks
0.论文摘要 卷积神经网络建立在卷积操作的基础上,通过融合局部感受野内的空间和通道信息来提取有意义的特征。为了增强网络的表示能力,最近的一些方法展示了增强空间编码的好处。在本研究中,我们专注于通道关系,并提出了一种新颖…...
【SPP】蓝牙串口协议(SPP)深度解析:从 RS232 仿真到设备互联的技术实现
目录 一、SPP协议概述 1.1 SPP的定位与核心功能 1.2 协议栈层次(SPP 协议模型) 1.3 技术原理 1.4 用户需求 二、设备角色与连接模型 2.1 角色定义(DevA 与 DevB 交互) 2.2 角色动态切换 2.3 协议依赖关系 三、数据传输:从 RS232 到蓝牙的映射 3.1 控制信号仿真…...
5.Excel:从网上获取数据
一 用 Excel 数据选项卡获取数据的方法 连接。 二 要求获取实时数据 每1分钟自动更新数据。 A股市场_同花顺行情中心_同花顺财经网 用上面方法将数据加载进工作表中。 在表格内任意区域右键,刷新。 自动刷新: 三 缺点 Excel 只能爬取网页上表格类型的…...
基于RFID技术建筑物资材料智能管理解决方案
建筑行业仓库和物资材料管理面临诸多挑战,如工程设备重复利用的管理需求、物资出入库管理不规范、账物不符、物资丢失等问题。特别是在复杂多变的工地环境中,对物资进行科学规范的管理难度极大。上海岳冉基于RFID技术的建筑物资材料智能管理解决方案聚焦…...
详解CountDownLatch底层源码
大家好,我是此林。 今天来分享一下CountDownLatch的底层源码。 CountDownLatch 是 Java 并发包 (java.util.concurrent) 中的线程之间同步工具类,主要用于协调多个线程的执行顺序。其核心思想是通过计数器实现线程间的"等待-唤醒"机制&#…...
Python每日一题(9)
Python每日一题 2025.3.29 一、题目二、分析三、源代码四、deepseek答案五、源代码与ai分析 一、题目 question["""企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%,利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部…...
一阶谓词逻辑表示法、产生式表示法、框架表示法深度对比
前文我们已经深度学习了一阶谓词逻辑表示法、产生式表示法和框架表示法这三种知识表示方法,那么它们之间有什么异同点呢?接下来我们对它们进行深度对比。 首先,我得回忆这三种知识表示方法的基本概念和特点。 (1)一阶谓词逻辑(FOPL)是基于形式逻辑的,使用谓词、变量、量…...
Tomcat生产服务器性能优化
试想以下这个情景:你已经开发好了一个程序,这个程序的排版很不错,而且有着最前沿的功能和其他一些让你这程序增添不少色彩的元素。可惜的是,程序的性能不怎么地。你也十分清楚,若现在把这款产品退出市场,肯…...
【算法day25】 最长有效括号——给你一个只包含 ‘(‘ 和 ‘)‘ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
32. 最长有效括号 给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。 https://leetcode.cn/problems/longest-valid-parentheses/ 2.方法二:栈 class Solution { public:int longestValid…...
Python之变量与数据类型总结
前言 一、基本数据类型 1、整数(int) 2、浮点数(float) 3、布尔值(bool) 4、字符串(str) 二、复合数据类型 1、列表(list) 1.1、列表基础 1.1.1、列…...
【大模型基础_毛玉仁】5.3 附加参数法:T-Patcher
目录 5.3 附加参数法:T-Patcher5.3.1 补丁的位置1)键值存储体2)补丁设计 5.3.2 补丁的形式5.3.3 补丁的实现1)准确性2)局部性 5.3 附加参数法:T-Patcher 附加参数法:通过引入可训练的额外参数实…...