C++ Primer 迭代器
专栏简介:本专栏主要面向C++初学者,解释C++的一些基本概念和基础语言特性,涉及C++标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级程序设计技术。希望对读者有帮助!
目录
- 3.4迭代器介绍
- 使用迭代器
- 迭代器运算符
- 将迭代器从一个元素移动到另外一个元素
- 迭代器类型
- begin和end运算符
- 结合解引用和成员访问操作
- 迭代器运算
- 迭代器的算术运算
- 使用迭代器运算
3.4迭代器介绍
我们已经知道可以使用下标运算符来访问string对象的字符或vector对象的元素,还有另外一种更通用的机制也可以实现同样的目的,这就是迭代器(iterator)。除了vector之外,标准库还定义了其他几种容器。所有标准库容器都可以使用逄代器,但是其中只有少数几种才同时支持下标运算符。严格来说,string对象不属于容器类型,但是string支持很多与容器类型类似的操作。vector支持下标运算符,这点和string一样;string支持迭代器,这也和vector是一样的。
类似于指针类型,迭代器也提供了对对象的间接访问。就迭代器而言,其对象是容器中的元素或者string对象中的字符。使用迭代器可以访问某个元素,迭代器也能从一个元素移动到另外一个元素。迭代器有有效和无效之分,这一点和指针差不多。有效的迭代器或者指向某个元素,或者指向容器中尾元素的下一位置;其他所有情况都属于无效。
使用迭代器
和指针不一样的是,获取迭代器不是使用取地址符,有迭代器的类型同时拥有返回迭代器的成员。比如,这些类型都拥有名为begin和end的成员,其中begin成员负责返回指向第一个元素(或第一个字符)的迭代器。如有下述语句:
//由编译器决定b和e的类型;
//b表示v的第一个元素,e表示y尾元素的下一位置
auto b=v.begin(),e=v.end();//b和e的类型相同
end成员则负责返回指向容器(或string对象)尾元素的下一位置(one past the end) 的迭代器,也就是说,该迭代器指示的是容器的一个本不存在的“尾后(off the end)“元
素。这样的迭代器没什么实际含义,仅是个标记而己,表示我们已经处理完了容器中的所有元素。end成员返回的迭代器常被称作尾后迭代器(off-the-end iterator)或者简称为尾
迭代器(end iterator)。特殊情况下如果容器为空,则begin和end返回的是同一个迭代器。
如果容器为空,则begin和end返回的是同一个迭代嚣,都是尾后迭代器
一般来说,我们不清楚(不在意)迭代器准确的类型到底是什么。在上面的例子中,使用auto关键字定义变量b和e(参见2.5.2节,第61页),这两个变量的类型也就是begin和end的返回值类型,第97页将对相关内容做更详细的介绍。
迭代器运算符
表3.6列举了迭代器支持的一些运算。使用==和!=来比较两个合法的迭代器是否相等,如果两个迭代器指向的元素相同或者都是同一个容器的尾后迭代器,则它们相等;否则就说这两个迭代器不相等。
表3.6:标准容器迭代器的运算符
*iter | 返回迭代器iter所指元素的引用 |
iter->mem | 解引用ttez并获取该元素的名为mem的成员,等价于(*iter).mem |
++iter | 令iter指示容器中的下一个元素 |
–iter | 令iter指示容器中的上一个元素 |
iter1==iter2 | 判断两个迭代器是否相等(不相等),如果两个迪代器指示的是同一个元 |
iter1 != iter2 | 素或者它们是同一个容器的尾后追代器,则相等;反之,不相等 |
和指针类似,也能通过解引用迭代器来获取它所指示的元素,执行解引用的选代器必须合法并确实指示着树个元素。试图解引用一个非法迢代器或者尾后迭代器都是未被定义的行为。
举个例子,程序利用下标运算符把string对象的第一个字母改为了大写形式:
strings(“some string“);
if(s.begin()!s.end())〔//确保s非空auto it=s.begin();//it表示s的第一个字符*it= toupper(*it);//将当前字符改成大写形式
)
本例首先检查s是否为空,显然通过检查begin和end返回的结果是否一致就能做到这一点。如果返回的结果一样,说明s为空;如果返回的结果不一样,说明s不为空,此时s中至少包含一个字符。
我们在i内部,声明了一个迭代器变量it并把begin返回的结果赋给它,这样就得到了指示s中第一个字符的迭代器,接下来通过解引用运算符将第一个字符更改为大写形式。和原来的程序一样,输出结果将是:
Some string
将迭代器从一个元素移动到另外一个元素
迭代器使用递增(++)运算符来从一个元素移动到下一个元素。从逻辑上来说,迭代器的递增和整数的递增类似,整数的递增是在整数值上“加1迭代器的递增则是将迭代器“向前移动一个位置“。
因为end 返回的迭代器并不实际指示某个元素,所以不能对其进行递增或解引用操作。
之前有一个程序把string对象中第一个单词改写为大写形式,现在利用迭代器及其递增运算符可以实现相同的功能:
//依次处理s的字符直至我们处理完全部字符或者遥到空白
for(auto it=s.begin();it!=s.end()&&!isspace(*it);++it)*it=toupper(*it);//将当前字符改成大写形式
上面的循环遍历s的字符直到遇到空白字符为止。
循环首先用s.begin的返回值来初始化it,意味着it指示的是s中的第一个字符(如果有的话)。条件部分检查是否已到达s的尾部,如果尚未到达,则将it解引用的结果传入isspace函数检查是否遇到了空白。每次迭代的最后,执行++it令迭代器前移-个位置以访问s的下一个字符。
循环体内部和上一个程序if语句内的最后一句话一样,先解引用it,然后将结果传入toupper函数得到该字母对应的大写形式,再把这个大写字母重新赋值给it所指示的字符。
迭代器类型
就像不知道string和vector的size_type成员到底是什么类型一样,一般来说我们也不知道(其实是无须知道)迭代器的精确类型。而实际上,那些拥有迭代器的标准库类型使用iterator和const iterator来表示迭代器的类型:
vector<int>::iterator it;//it能读写vector<itnt>的元素
string::iterator it2;//it2能读写string对象中的字符vector<int>::const_iterator it3;//it3只能读元素,不能写元素
string::const_iterator it4;//it4只能读字符,不能写字符
const_iterator和常量指针差不多,能读取但不能修改它所指的元素值。相反,iterator的对象可读可写。如果vector对象或string对象是一个常量,只能使const iterator;如果vector对象或string对象不是常量, 那么既能使用iterator也能使用const_iterator。
begin和end运算符
begin和end返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回const_iterator;如果对象不是常量,返回iterator:
vector<int> v;
const vector<int> cv;
auto it1 = v.begin();//it1的类型是vector<int>::tterator
auto it2 = cv.begin();//it2的类型是vector<int>::const_iterator
有时候这种默认的行为些非我们所要。如果对象只需读操作而无须写操作的话最好使用常量类型(比如const_iterator)。为了便于专门得到const_iterator类型的返回值,C++11新标准引入了两个新函数,分别是cbegin:
auto it3 = v.cpegin();//it3的类型是vector<int>::const_tterator
类似于begin和end,上述两个新函数也分别返回指示容器第一个元素或最后元素下一位置的迭代器。有所不同的是,不论vector对象(或string对象)本身是否是常量,返回值都是const_iterator。
结合解引用和成员访问操作
解引用迭代器可获得迭代器所指的对象,如果该对象的类型恰好是类,就有可能希望进一步访问它的成员。例如,对于一个由字符串组成的vector对象来说,要想检查其元素是否为空,令it是该vector对象的迭代器,只需检查it所指宇符串是否为空就可以了,其代码如下所示:
(*it).empty()
注意,(*it).empty()中的圆括号必不可少,该表达式的含义是先对it解引用,然后解引用的结果再执行点运算符。如果不加圆括号,点运算符将由it来执行,而非it解引用的结果:
(*it).empty() //解引用it,然后调用结果对象的empty成员
*it.empty()// 错误:试图访问it的名为empty的成员,但it是个选代器,
// 没有empty成员
上面第二个表达式的含义是从名为it的对象中寻找其empty成员,显然it是一个迭代器,它没有哪个成员是叫empty的,所以第二个表达式将发生错误。
为了简化上述表达式,C++语言定义了箭头运算符(->)。箭头运算符把解引用和成员访问两个操作结合在一起,也就是说,it->mem和(*it).mem表达的意思相同。
例如,假设用一个名为text的字符串向量存放文本文件中的数据,其中的元素或者是一句话或者是一个用于表示段落分隔的空字符串。如果要输出text中第一段的内容,可以利用迭代器写一个循环令其遍历text,直到遇到穿字符串的元素为止:
//依次输出text的每一行直至遇到第一个空白行为止
for(auto it=text.cbegin();it != text.cend()&& it->empty();++it)
cout<< *it << endl;
我们首先初始化it令其指向text的第一个元素,循环重复执行直至处理完了text的所有元素或者发现某个元素为空。每次迭代时只要发现还有元素并且尚未遇到空元素,就输
出当前正在处理的元素。值得注意的是,因为循环从头到尾只是读取text的元素而未向其中写值,所以使用了cbegin和cend来控制整个迭代过程。
某些对vector对象的操作会使迭代器失效
虽然vector对象可以动态地增长,但是也会有些副作用。已知的一个限制是不能在范围for循环中向vector对象添加元素。另外一个限制是任何一种可能改变vector对象容量的操作,比如push_back,都会使该vector对象的迭代器失效。
迭代器运算
迭代器的递增运算令迭代器每次移动一个元素,所有的标准库容器都有支持递增运算的迭代器。类似的,也能用==和!=对任意标准库类型的两个有效迭代器进行比较。
string和vector的迭代器提供了更多额外的运算符,一方面可使得迭代器的每次移动跨过多个元素,另外也支持迭代器进行关系运算。所有这些运算被称作迭代器运算
(iterator arithmetic,其细节由表3.7列出。
表3.7:vector和string迭代器支持的运算
iter + n | 迭代器加上一个整数值仍得一个迪代器,迭代器指示的新位置与原米相比向前移动了若干个元素。结果迪代器或者指示容器内的一个元素,或者指示容器尾元素的下一位置 |
itter-n | 迭代器凑去一个整数值仍得一个迪代器,迭代器指示的新位置与原来相比向后移动了若干个元素。结果迭代器或者指示容器内的一个元素,或者指示容器尾元素的下一位置 |
iter1+=n | 迭代器加法的复合赋值语句,将iter1加n的结果赋给iter1 |
iter1-=n | 迭代器减法的复合赋值语句,将iter1减n的结果赋给iter1 |
iter1-iter2 | 两个迭代器相减的结果是它们之间的距离,也就是说,将运算符右侧的迭代器向前移动差值个元素后将得到左侧的迭代器。参与运算的两个迭代器必须指向的是同一个容器中的元素或尾元素的下一个位置 |
>,>=,<,<= | 迭代嚣的关系运算符,如果某迭代器指向的容器位置在另一个迭代器所指位置之前,则说前者小于后者。参与运算的两个迭代器必须指向的是同一个容器中的元素或者尾元素的下一位置 |
迭代器的算术运算
可以令迭代器和一个整数值相加〔或相减),其返回值是向前〔或向后)移动了若干个位置的迭代器。执行这样的操作时,结果迭代器或者指示原vector对象(或string对象)内的一个元素,或者指示原vector对象(或string对象)尾元素的下一位置。
举个例子,下面的代码得到一个迭代器,它指向vector对象中间位置的元素:
//计算得到最接近vi中间元素的一个选代器
auto mid=vi.begin()+vi.size()/2;
如果vi有20个元素,vi.size()/2得10,此例中即令mid等于vi.begin(1+10)。已知下标从0开始,则迭代器所指的元素是vi[10],也就是从首元素开始向前相隔10个位置的那个元素。
对于string或vector的迭代器来说,除了判断是否相等,还能使用关系运算符(<=、>、>=)对其进行比较。参与比较的两个迭代器必须合法而且指向的是同一个容器的元素(或者尾元素的下一位置)。例如,假设it和mid是同一个vector对象的两个迭代器,可以用下面的代码来比较它们所指的位置孰前孰后:
if(it<mid)
//处理vi前半部分的元素
只要两个迭代器指向的是同一个容器中的元素或者尾元素的下一位置,就能将其相减,所得结果是两个迭代器的距离。所谓距离指的是右侧的迭代器向前移动多少位置就能追上左侧的迭代器,其类型是名为adifference_type的带符号整型数。string和vector都定义了adifference_type,因为这个距离可正可负,所以difference_type是带符号类型的。
使用迭代器运算
使用迭代器运算的一个经典算法是二分搜索。二分搜索从有序序列中寻找某个给定的值。二分搜索从序列中间的位置开始搜索,如果中间位置的元素正好就是要找的元素,搜索完成;如果不是,假如该元素小于要找的元素,则在序列的后半部分继续搜素;假如该元素大于要找的元素,则在序列的前半部分继续搜索。在缩小的范围中计算一个新的中间元素并重复之前的过程,直至最终找到目标或者没有元素可供继续搜索。
下面的程序使用迭代器完成了二分搜索:
//text必须是有序的
//beg和end表示我们搜索的范国
auto beg=text.begin(), end=text.end();
auto mid=text.begin()+(end-beg)/2; //初始状态下的中间点
//当还有元素尚未格查并且我们还没有找到sought时执行循环while(mid!=end&&*mid!=sought){if(sought<*mid)//我们要找的元素在前半部分吗?end=mid;//如果是,调整搜索范围使得忽略掉后半部分else//我们要找的元素在后半部分beg=mid+1;//在mid之后寻找mid=beg+(end-beg)/2;//新的中间点
}
程序的一开始定义了三个迭代器:beg指向搜索范围内的第一个元素、end指向尾元素的下一位置、mid指向中间的那个元素。初始状态下,搜索范围是名为text的vector的全部范围。
循环部分先检查搜索范围是否为空,如果mid和end的当前值相等,说明已经找遍了所有元素。此时条件不满足,循环终止。当搜索范围不为空时,可知mid指向了某个元素,检查该元素是否就是我们所要搜索的,如果是,也终止循环当进入到循环体内部后,程序通过某种规则移动beg或者end来缩小搜索的范围。如果mid所指的元素比要找的元素sought大,可推测若text含有sought,则必出现在mid所指元素的前面。此时,可以忽略mid后面的元素不再查找,并把mid赋给end即可。另一种情况,如果mid比sought小,则要找的元素必出现在mid所指元素的后面。此时,通过令beg指向mid的下一个位置即可改变搜索范围。因为已经验证过mid不是我们要找的对象,所以在接下来的搜索中不必考虑它。
循环过程终止时,mid或者等于end或者指向要找的元素。如果mid等于end,说明text中没有我们要找的元素。
相关文章:
C++ Primer 迭代器
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
排序算法--归并排序
归并排序是分治法的经典实现,适合大规模数据排序,尤其适合需要稳定排序的场景(如数据库排序) #include <stdlib.h> // 用于动态内存分配 // 合并两个已排序的子数组 void merge(int arr[], int left, int mid, int right) …...
深入探讨DICOM医学影像中的WADO服务及其具体实现
1. 引言 随着数字化医学影像技术的普及,如何高效、安全地存储、管理和共享医学影像数据成为医疗行业亟待解决的关键问题。DICOM(Digital Imaging and Communications in Medicine)作为国际公认的医学影像标准,在全球范围内广泛应…...
自定义数据集 使用paddlepaddle框架实现逻辑回归
导入必要的库 import numpy as np import paddle import paddle.nn as nn 数据准备: seed1 paddle.seed(seed)# 1.散点输入 定义输入数据 data [[-0.5, 7.7], [1.8, 98.5], [0.9, 57.8], [0.4, 39.2], [-1.4, -15.7], [-1.4, -37.3], [-1.8, -49.1], [1.5, 75.6…...
信息学奥赛一本通 2112:【24CSPJ普及组】地图探险(explore) | 洛谷 P11228 [CSP-J 2024] 地图探险
【题目链接】 ybt 2112:【24CSPJ普及组】地图探险(explore) 洛谷 P11228 [CSP-J 2024] 地图探险 【题目考点】 1. 模拟 2. 二维数组 3. 方向数组 在一个矩阵中,当前位置为(sx, sy),将下一个位置与当前位置横纵坐…...
xxl-job 在 Java 项目的使用 以一个代驾项目中的订单模块举例
能搜到这里的最起码一定知道 xxl-job 是用来干什么的,我就不多啰嗦怎么下载以及它的历史了 首先我们要知道 xxl-job 这个框架的结构,如下图: xxl-job-master:xxl-job-admin:调度中心xxl-job-core:公共依赖…...
javaEE-8.JVM(八股文系列)
目录 一.简介 二.JVM中的内存划分 JVM的内存划分图: 堆区:编辑 栈区:编辑 程序计数器:编辑 元数据区:编辑 经典笔试题: 三,JVM的类加载机制 1.加载: 2.验证: 3.准备: 4.解析: 5.初始化: 双亲委派模型 概念: JVM的类加…...
模型/O功能之提示词模板
文章目录 模型/O功能之提示词模板什么是提示词模板提示词模板的输入和输出 使用提示词模板构造提示词 模型/O功能之提示词模板 在LangChain框架中,提示词不是简单的字符串,而是一个更复杂的结构,是一个“提示词工程”。这个结构中包含一个或多…...
[Proteus仿真]基于51单片机的智能温控系统
[Proteus仿真]基于51单片机的智能温控系统 基于51单片机的智能温控系统:DS18B20精准测温LCD1602双屏显示三键设置上下限声光报警,支持温度校准、抗干扰设计、阈值记忆。 一.仿真原理图 二.模块介绍 温度采集模块(DS18B20࿰…...
掌握 HTML5 多媒体标签:如何在所有浏览器中顺利嵌入视频与音频
系列文章目录 01-从零开始学 HTML:构建网页的基本框架与技巧 02-HTML常见文本标签解析:从基础到进阶的全面指南 03-HTML从入门到精通:链接与图像标签全解析 04-HTML 列表标签全解析:无序与有序列表的深度应用 05-HTML表格标签全面…...
ChatGPT与GPT的区别与联系
ChatGPT 和 GPT 都是基于 Transformer 架构的语言模型,但它们有不同的侧重点和应用。下面我们来探讨一下它们的区别与联系。 1. GPT(Generative Pre-trained Transformer) GPT 是一类由 OpenAI 开发的语言模型,基于 Transformer…...
浅谈线段树
文章同步发布于洛谷,建议前往洛谷查看。 前言 蒟蒻终于学会线段树(指【模板】线段树 1 1 1)啦! 线段树思想 我们先来考虑 P3372(基础线段树模板题)给的操作: 区间修改(增加&am…...
深度解读 Docker Swarm
一、引言 随着业务规模的不断扩大和应用复杂度的增加,容器集群管理的需求应运而生。如何有效地管理和调度大量的容器,确保应用的高可用性、弹性伸缩和资源的合理分配,成为了亟待解决的问题。Docker Swarm 作为 Docker 官方推出的容器集群管理工具,正是在这样的背景下崭露头…...
在线知识库的构建策略提升组织信息管理效率与决策能力
内容概要 在线知识库作为现代企业信息管理的重要组成部分,具有显著的定义与重要性。它不仅为组织提供了一个集中存储与管理知识的平台,还能够有效提升信息检索的效率,促进知识的创新和利用。通过这样的知识库,企业可以更好地应对…...
网件r7000刷回原厂固件合集测评
《网件R7000路由器刷回原厂固件详解》 网件R7000是一款备受赞誉的高性能无线路由器,其强大的性能和可定制性吸引了许多高级用户。然而,有时候用户可能会尝试第三方固件以提升功能或优化网络性能,但这也可能导致一些问题,如系统不…...
为什么命令“echo -e “\033[9;0]“ > /dev/tty0“能控制开发板上的LCD不熄屏?
为什么命令"echo -e “\033[9;0]” > /dev/tty0"能控制开发板上的LCD不熄屏? 在回答这个问题前请先阅读我之前写的与tty和终端有关的博文 https://blog.csdn.net/wenhao_ir/article/details/145431655 然后再来看这条命令的解释就要容易些了。 这条…...
vscode软件操作界面UI布局@各个功能区域划分及其名称称呼
文章目录 abstract检查用户界面的主要区域官方文档关于UI的介绍 abstract 检查 Visual Studio Code 用户界面 - Training | Microsoft Learn 本质上,Visual Studio Code 是一个代码编辑器,其用户界面和布局与许多其他代码编辑器相似。 界面左侧是用于访…...
【Java基础-42.3】Java 基本数据类型与字符串之间的转换:深入理解数据类型的转换方法
在 Java 开发中,基本数据类型与字符串之间的转换是非常常见的操作。无论是从用户输入中读取数据,还是将数据输出到日志或界面,都需要进行数据类型与字符串之间的转换。本文将深入探讨 Java 中基本数据类型与字符串之间的转换方法,…...
【ActiveMq RocketMq RabbitMq Kafka对比】
以下是 ActiveMQ、RocketMQ、RabbitMQ 和 Kafka 的对比表格,从复杂性、功能、性能和适用场景等方面进行整理: 特性ActiveMQRocketMQRabbitMQKafka开发语言JavaJavaErlangScala/Java协议支持AMQP、STOMP、MQTT、OpenWire 等自定义协议AMQP、STOMP、MQTT …...
csapp笔记3.6节——控制(1)
本节解决了x86-64如何实现条件语句、循环语句和分支语句的问题 条件码 除了整数寄存器外,cpu还维护着一组单个位的条件码寄存器,用来描述最近的算数和逻辑运算的某些属性。可检测这些寄存器来执行条件分支指令。 CF(Carry Flag)…...
网站快速收录:如何优化网站音频内容?
本文转自:百万收录网 原文链接:https://www.baiwanshoulu.com/60.html 为了优化网站音频内容以实现快速收录,以下是一些关键的策略和步骤: 一、高质量音频内容创作 原创性: 确保音频内容是原创的,避免使…...
音视频入门基础:RTP专题(8)——使用Wireshark分析RTP
一、引言 通过Wireshark可以抓取RTP数据包,该软件可以从Wireshark Go Deep 下载。 二、通过Wireshark抓取RTP数据包 首先通过FFmpeg将一个媒体文件转推RTP,生成RTP流: ffmpeg -re -stream_loop -1 -i input.mp4 -vcodec copy -an -f rtp …...
4-图像梯度计算
文章目录 4.图像梯度计算(1)Sobel算子(2)梯度计算方法(3)Scharr与Laplacian算子4.图像梯度计算 (1)Sobel算子 图像梯度-Sobel算子 Sobel算子是一种经典的图像边缘检测算子,广泛应用于图像处理和计算机视觉领域。以下是关于Sobel算子的详细介绍: 基本原理 Sobel算子…...
深入解析 Redis AOF 机制:持久化原理、重写优化与 COW 影响
深入解析 Redis AOF 机制:持久化原理、重写优化与 COW 影响 1. 引言2. AOF 机制详解2.1 AOF 解决了什么问题?2.2 AOF 写入机制2.2.1 AOF 的基本原理2.2.2 AOF 运行流程2.2.3 AOF 文件刷盘策略 3. AOF 重写机制3.1 AOF 文件为什么会变大?3.2 解…...
机器学习day8
自定义数据集 ,使用朴素贝叶斯对其进行分类 代码 import numpy as np import matplotlib.pyplot as pltclass1_points np.array([[2.1, 2.2], [2.4, 2.5], [2.2, 2.0], [2.0, 2.1], [2.3, 2.3], [2.6, 2.4], [2.5, 2.1]]) class2_points np.array([[4.0, 3.5], …...
【前端】ES6模块化
文章目录 1. 模块化概述1.1 什么是模块化?1.2 为什么需要模块化? 2. 有哪些模块化规范3. CommonJs3.1 导出数据3.2 导入数据3.3 扩展理解3.4 在浏览器端运行 4.ES6模块化 参考视频地址 1. 模块化概述 1.1 什么是模块化? 将程序文件依据一定规则拆分成多个文件,这种编码方式…...
【leetcode练习·二叉树拓展】快速排序详解及应用
本文参考labuladong算法笔记[拓展:快速排序详解及应用 | labuladong 的算法笔记] 1、算法思路 首先我们看一下快速排序的代码框架: def sort(nums: List[int], lo: int, hi: int):if lo > hi:return# 对 nums[lo..hi] 进行切分# 使得 nums[lo..p-1]…...
Gurobi基础语法之 addConstr, addConstrs, addQConstr, addMQConstr
在新版本的 Gurobi 中,向 addConstr 这个方法中传入一个 TempConstr 对象,在模型中就会根据这个对象生成一个约束。更重要的是:TempConstr 对象可以传给所有addConstr系列方法,所以下面先介绍 TempConstr 对象 TempConstr TempC…...
游戏引擎 Unity - Unity 设置为简体中文、Unity 创建项目
Unity Unity 首次发布于 2005 年,属于 Unity Technologies Unity 使用的开发技术有:C# Unity 的适用平台:PC、主机、移动设备、VR / AR、Web 等 Unity 的适用领域:开发中等画质中小型项目 Unity 适合初学者或需要快速上手的开…...
Kamailio、MySQL、Redis、Gin后端、Vue.js前端等基于容器化部署
基于容器化的部署方案,通常会将每个核心服务(如Kamailio、MySQL、Redis、Gin后端、Vue.js前端等)独立运行在不同的容器中,通过Docker或Kubernetes统一管理。以下是具体实现方式和关键原因: 1. 容器化部署的核心思路 每…...
从1号点到n号点最多经过k条边的最短距离
目录 解析方法思路代码解释代码逐行注释1. 头文件和常量定义:2.边的结构体:3.全局变量:4.Bellman-Ford算法实现:5.主函数: 注意事项代码含义为什么需要 backup[a]?举例说明关键点 总结 解析 要实现从1号点…...
模拟实战-用CompletableFuture优化远程RPC调用
实战场景 这是广州某500-900人互联网厂的面试原题 手写并发优化解决思路 我们要调用对方的RPC接口,我们的RPC接口每调用一次对方都会阻塞50ms 但是我们的业务要批量调用RPC,例如我们要批量调用1k次,我们不可能在for循环里面写1k次远程调用…...
【pinia状态管理配置】
pinia状态管理配置 安装main.ts引入自定义user仓库使用自定义仓库 安装 pnpm add piniamain.ts引入 // createPinia() 函数调用创建了一个新的 Pinia 实例。 // 这个实例是状态管理的核心,它将管理应用中所有的 store。 import { createPinia } from pinia app.us…...
SpringBoot 引⼊MybatisGenerator
SpringBoot 引⼊MybatisGenerator 1. 引入插件2. 添加generator.xml并修改3. 生成文件 1. 引入插件 <plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.5</vers…...
在线销售数据集分析:基于Python的RFM数据分析方法实操训练
一、前言 个人练习,文章用于记录自己的学习练习过程,分享出来和大家一起学习。 数据集:在线销售数据集 分析方法:RFM分析方法 二、过程 1.1 库的导入与一些必要的初始设置 import pandas as pd import datetime import matplo…...
LeetCode - #197 Swift 实现找出温度更高的日期
网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...
分析哲学:从 语言解剖到 思想澄清的哲学探险
分析哲学:从 语言解剖 到 思想澄清 的哲学探险 第一节:分析哲学的基本概念与公式解释 【通俗讲解,打比方来讲解!】 分析哲学,就像一位 “语言侦探”,专注于 “解剖语言”,揭示我们日常使用的语…...
C++【iostream】数据库的部分函数功能介绍
在 C 编程世界中,iostream 库扮演着举足轻重的角色,它是 C 标准库的核心组成部分,为程序提供了强大的输入输出功能。无论是简单的控制台交互,还是复杂的文件操作,iostream 库都能提供便捷高效的解决方案。本文将深入剖…...
金山打字游戏2010绿色版,Win7-11可用DxWnd完美运行
金山打字游戏2010绿色版,Win7-11可用DxWnd完美运行 链接:https://pan.xunlei.com/s/VOIAYCzmkbDfdASGJa_uLjquA1?pwd67vw# 进入游戏后,如果输入不了英文字母(很可能是中文输入状态),就按一下“Shift”键…...
洛谷[USACO08DEC] Patting Heads S
题目传送门 题目难度:普及/提高一 题面翻译 今天是贝茜的生日,为了庆祝自己的生日,贝茜邀你来玩一个游戏。 贝茜让 N N N ( 1 ≤ N ≤ 1 0 5 1\leq N\leq 10^5 1≤N≤105) 头奶牛坐成一个圈。除了 1 1 1 号与 N N N 号奶牛外࿰…...
讲清逻辑回归算法,剖析其作为广义线性模型的原因
1、逻辑回归算法介绍 逻辑回归(Logistic Regression)是一种广义线性回归分析模型。虽然名字里带有“回归”两字,但其实是分类模型,常用于二分类。既然逻辑回归模型是分类模型,为什么名字里会含有“回归”二字呢?这是因为其算法原…...
基于STM32的智能安防监控系统
1. 引言 随着物联网技术的普及,智能安防系统在家庭与工业场景中的应用日益广泛。本文设计了一款基于STM32的智能安防监控系统,集成人体感应、环境异常检测、图像识别与云端联动功能,支持实时报警、远程监控与数据回溯。该系统采用边缘计算与…...
八. Spring Boot2 整合连接 Redis(超详细剖析)
八. Spring Boot2 整合连接 Redis(超详细剖析) 文章目录 八. Spring Boot2 整合连接 Redis(超详细剖析)2. 注意事项和细节3. 最后: 在 springboot 中 , 整合 redis 可以通过 RedisTemplate 完成对 redis 的操作, 包括设置数据/获取数据 比如添加和读取数据 具体整…...
220.存在重复元素③
目录 一、题目二、思路三、解法四、收获 一、题目 给你一个整数数组 nums 和两个整数 indexDiff 和 valueDiff 。 找出满足下述条件的下标对 (i, j): i ! j, abs(i - j) < indexDiff abs(nums[i] - nums[j]) < valueDiff 如果存在,返回 true &a…...
【Linux】从硬件到软件了解进程
个人主页~ 从硬件到软件了解进程 一、冯诺依曼体系结构二、操作系统三、操作系统进程管理1、概念2、PCB和task_struct3、查看进程4、通过系统调用fork创建进程(1)简述(2)系统调用生成子进程的过程〇提出问题①fork函数②父子进程关…...
volatile变量需要减少读取次数吗
问题说明 本人在前期读Netty源码时看到这样一段源码和注释: private boolean invokeHandler() {// Store in local variable to reduce volatile reads.int handlerState this.handlerState;return handlerState ADD_COMPLETE || (!ordered && handlerS…...
红黑树的封装
一、封装思路 在 STL 中 map set 的底层就是封装了一棵红黑树。 其中连接红黑树和容器的是迭代器,map set 暴露出的接口都不是自己写的,而是红黑树写的,外部接口封装红黑树接口。 所以写出红黑树为 map set 写的接口,再在上层的…...
Java 泛型<? extends Object>
在 Java 泛型中,<? extends Object> 和 <?> 都表示未知类型,但它们在某些情况下有细微的差异。泛型的引入是为了消除运行时错误并增强类型安全性,使代码更具可读性和可维护性。 在 JDK 5 中引入了泛型,以消除编译时…...
TensorFlow简单的线性回归任务
如何使用 TensorFlow 和 Keras 创建、训练并进行预测 1. 数据准备与预处理 2. 构建模型 3. 编译模型 4. 训练模型 5. 评估模型 6. 模型应用与预测 7. 保存与加载模型 8.完整代码 1. 数据准备与预处理 我们将使用一个简单的线性回归问题,其中输入特征 x 和标…...
解码大数据的四个V:体积、速度、种类与真实性
解码大数据的四个V:体积、速度、种类与真实性 在大数据领域,有一个大家耳熟能详的概念——“四个V”:Volume(体积)、Velocity(速度)、Variety(种类)、Veracityÿ…...