当前位置: 首页 > news >正文

C++STL之vector(超详细)

C++STL之vector

  • 1.vector基本介绍
  • 2.vector重要接口
    • 2.1.构造函数
    • 2.2.迭代器
    • 2.3.空间
      • 2.3.1.resize
      • 2.3.2.capacity
    • 2.4.增删查找
  • 3.迭代器失效
  • 4.迭代器分类

🌟🌟hello,各位读者大大们你们好呀🌟🌟
🚀🚀系列专栏:【C++的学习】
📝📝本篇内容:vector基本介绍;vector重要接口:构造函数;迭代器;空间;增删查改;迭代器失效;迭代器分类
⬆⬆⬆⬆上一篇:C++IO流
💖💖作者简介:轩情吖,请多多指教(> •̀֊•́ ) ̖́-

1.vector基本介绍

① 在我们C语言中有数组,C++中因此也设计了array来代替C语言中的数组,但是它有一个缺点,就是array是静态空间,一旦配置了空间就无法改变,这就让使用者非常麻烦。但是vector就不一样,它是动态空间,一旦底层空间不足,就会自动扩容,压根不需要担心空间不足而造成问题。
②vector扩容:当新元素插入进来时,发现内存不足,这个时候就会先扩容开辟新的空间(并不是原地扩容,因为可能后面没有内存),然后把原来的数据拷贝过去,再进行插入,然后把旧的空间给释放掉。并且我们扩容的空间基本上是以倍数来增长的,保证后续再有元素插入时,不需要扩容,导致效率低下。
③vector支持随机访问,即像数组一样[ ]来访问,非常高效,同时在末尾删除和末尾插入元素非常高效,这得益于它的结构。但是其他的位置进行操作效率就会比较低下,没有list好

2.vector重要接口

☞vector参考文档

2.1.构造函数

对于任何容器,首先看的肯定是构造函数
在这里插入图片描述
讲一下其中比较重要的

vector构造函数
vector()默认构造函数
vector(const vector&)拷贝构造
vector(size_type n,const value_type&val)构造n个val
vector(InputIterator first, InputIterator last)使用迭代器构造
#include <vector>
#include <iostream>
using namespace std;
int main()
{vector<int> v1;//默认构造int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };vector<int> v2(arr, arr + 10);//使用迭代器来构造for (auto& e : v2){cout << e << " ";}cout << endl;vector<int> v3(2, 10);//构造2个为10的元素for (auto& e : v3){cout << e <<" ";}vector<int> v4(v3);//拷贝构造return 0;
}

在这里插入图片描述

2.2.迭代器

我们来看一下迭代器,迭代器就是迭代器是一种访问容器内元素的对象,它提供了一种方法来顺序访问容器中的各个元素,而不需要了解容器的内部工作原理。

vector迭代器iterator/reverse_iterator
begin+end正向迭代器
rbegin+rend反向迭代器
#include <iostream>
#include <vector>
using namespace std;
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };vector<int> v(arr, arr + 10);//使用迭代器//正向迭代器vector<int>::iterator it = v.begin();while (it != v.end())//end是最后一个元素的下一个位置{cout << *it <<' ';//像指针一样使用it++;}cout << endl;//反向迭代器vector<int>::reverse_iterator rit = v.rbegin();while (rit != v.rend()){cout << *rit << ' ';//像指针一样使用rit++;//这里是++,而不是--,因为已经说明是反向迭代器,就该使用++}return 0;
}

在这里插入图片描述

2.3.空间

vector空间
size_type size() const;获取数据个数
size_type capacity() const;获取vector的容量大小
bool empty() const;vector是否为空
void reserve (size_type n);提前开辟空间,只会改变vector的capacity,能够缓解vector增容代价问题
void resize (size_type n, value_type val = value_type());改变vector的size,可以变大也可以变小
#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v;//emptyif (v.empty()){cout << "empty" << endl;}cout << "------------------" << endl;//sizev.push_back(10);v.push_back(10);v.push_back(10);cout << v.size() << endl;cout << "------------------" << endl;//capacitycout << v.capacity() << endl;cout << "------------------" << endl;//reversev.reserve(10);//提前扩容到能存放10个元素的空间cout << v.size() << endl;//3,不会改变cout << v.capacity() << endl;//10cout << "------------------" << endl;//resizev.resize(20);cout << v.size() << endl;//20,改变size,元素为默认值cout << v.capacity() << endl;//20return 0;
}

在这里插入图片描述

2.3.1.resize

其中我们的resize还有其他的功能,可以缩小空间以及设定自己想要的元素,resize在开空间的同时还会进行初始化,影响size
具体演示见下面

#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v;v.push_back(10);v.push_back(11);v.push_back(12);v.push_back(13);v.push_back(14);cout <<"size:"<<v.size() << endl;for (auto& e : v){cout << e << " ";}cout << endl;cout << "---------------------" << endl;v.resize(3);cout << "size:" << v.size() << endl;for (auto& e : v){cout << e << " ";}cout << endl;cout << "---------------------" << endl;v.resize(10,33);//把7个元素都设置为33cout << "size:" << v.size() << endl;for (auto& e : v){cout << e << " ";}cout << endl;cout << "---------------------" << endl;return 0;
}

在这里插入图片描述

2.3.2.capacity

我们这边再详细讨论一下capacity这个成员函数,我们想一下,我们的vector的扩容是按照什么来的呢?需要空间就扩容?一个个扩容?我们来看一下下面的一段代码,分别在windows和Linux下展示

#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v;size_t cap = v.capacity();cout <<"initital capacity:"<< cap << endl;for (int i = 0; i < 100; i++){v.push_back(i);if (cap != v.capacity()){cap = v.capacity();cout << "capacity changed:" << cap << endl;}} return 0;
}

windows:
在这里插入图片描述

Linux:
在这里插入图片描述

capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。

我们还要注意下它的效率问题,如果我们提前知道需要多少空间,就可以提前扩容来保证一次的开辟空间,来避免多次扩容的效率低下

#include <iostream>
#include  <vector>
using namespace std;
int main()
{vector<int> v;v.reserve(100);//提前开辟好空间,防止一遍遍的扩容造成效率低下for (int i = 0; i < 100; i++){v.push_back(i);}cout << v.capacity() << endl;//100return 0;
}

2.4.增删查找

vector增删查改
void push_back (const value_type& val);尾插
void pop_back();尾删
InputIterator find (InputIterator first, InputIterator last, const T& val);这是算法中的,查找
iterator insert (iterator position, const value_type& val);在position前插入元素
void insert (iterator position, size_type n, const value_type& val);在position位置前插入n个val
iterator erase (iterator position);删除position位置的元素
iterator erase (const_iterator first, const_iterator last);删除迭代器范围的元素
void swap (vector& x);交换两个vector
reference operator[] (size_type n);像数组一样的访问
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{vector<int> v(2, 10);v.push_back(11);//尾插v.push_back(12);v.push_back(13);v.push_back(14);cout << "initiatl element:";for (auto& e : v){cout << e << " ";}cout << endl;cout << "------------------------------------------------------" << endl;v.pop_back();//尾删cout << "after pop_back():";for (auto& e : v){cout << e << " ";}cout << endl;cout << "------------------------------------------------------" << endl;v.insert(v.begin(), 9);//在第一个元素前的位置插入一个9cout << "after insert(v.begin(),9):";for (auto& e : v){cout << e << " ";}cout << endl;cout << "------------------------------------------------------" << endl;//find && erasevector<int>::iterator it=find(v.begin(), v.end(),12);//查找元素为12的位置if (it != v.end()){//如果返回的迭代器为end()说明没找到v.erase(it);}cout << "after erase(it):";for (auto& e : v){cout << e << " ";}cout << endl;cout << "------------------------------------------------------" << endl;//operator[]for (int i = 0; i < v.size(); i++){v[i] = i;//operator[]的返回值是引用}cout << "after change element through operator[]:";for (auto& e : v){cout << e << " ";}cout << endl;cout << "------------------------------------------------------" << endl;return 0;
}

在这里插入图片描述

3.迭代器失效

接下来我们要谈谈迭代器失效的问题了,这个如果不了解底层的话就会很容易掉进坑里面
首先我们先讲insert导致的迭代器失效
在这里插入图片描述
在我们使用insert的时候,如果空间不足了,那我们的vector就会自动帮我们扩容,但是扩容常常需要经历三个步骤:开辟新的空间;移动元素到新空间;释放原来的空间。我们vector底层的实现的迭代器本身就是指针,只不过是typedef了一下。仔细想想,问题就来了,当我们插入后,有概率空间不足,扩容后,原本的迭代器(指针)就是野指针了,没有指向新空间

//!!!!error code
#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v;v.push_back(11);v.push_back(12);v.push_back(13);v.push_back(14);cout << v.capacity() << endl;//接下来再插入就会扩容	vector<int>::iterator it = v.begin();v.insert(it, 10);cout << v.capacity() << endl;cout << *it << endl;return 0;
}

上述代码就演示了这个情况,使用一块已经被释放的空间,造成的后果是程序崩溃,我们仅仅演示了一下insert造成的结果,其实其他会造成扩容的函数如resize,reverse,push_back都会造成迭代器失效,同时从另一个角度来说,我们所传入的迭代器position所指向的内容已经不是我们想要的了,这也是迭代器失效的一种情况,因此insert以后我们认为迭代器已经失效,不能再使用

下一种情况是erase,思考一下?erase会扩容吗?答案是并不会,只是删除元素,所以说就没问题了?不不不,仔细思考一下,我的迭代器此时指向最后一个元素,如果我erase了一个元素呢,我们底层的_finish指针就会–,那此时的迭代器就相等于是指向无效空间

//!!!!!error code
#include <iostream>
using namespace std;
#include <vector>
int main()
{int a[] = { 1, 2, 3, 4 };vector<int> v(a, a + sizeof(a) / sizeof(int));// 使用find查找3所在位置的iteratorvector<int>::iterator pos = find(v.begin(), v.end(), 3);// 删除pos位置的数据,导致pos迭代器失效。v.erase(pos);cout << *pos << endl; // 此处会导致非法访问return 0;
}

在这里插入图片描述

可以运行一下上面的代码分别在Linux和Windows下,在Windows下会崩溃,但是在Linux可以运行,这不得不说VS的检查非常严,erase后的迭代器是不允许使用的,但是g++的就会宽很多,当删除3后,元素4会往前移动,pos的位置还是有效的
接下来就看一下下面这个代码

#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v{1,2,3,4,5};//删除偶数vector<int>::iterator it = v.begin();while (it != v.end()){if ((*it) % 2 == 0){v.erase(it);}it++;}for (auto& e : v){cout << e << " ";}cout << endl;return 0;
}

首先对于环境而言是一样的,在VS下会崩溃,而Linux下能正常运行
在这里插入图片描述
在这里插入图片描述
我们来分析一下这个代码
在这里插入图片描述
可以发现,我们的it很巧合的把偶数元素删除了,同时也正好落到了_finish使用空间的尾end(),也判断循环结束了,我们接下里对代码稍作修改如下

#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v{ 1,2,3,4};//删除偶数vector<int>::iterator it = v.begin();while (it != v.end()){if ((*it) % 2 == 0){v.erase(it);}it++;}for (auto& e : v){cout << e << " ";}cout << endl;return 0;
}

我们的元素的数量变为只有四个,接下来再看一下它的执行逻辑
在这里插入图片描述
通过上面的图可以发现,我们的it直接和_finish(end())直接错过了,这样即使是Linux也无能为力了
在这里插入图片描述
直接发生段错误

从上述的例子中可以看到:SGI STL中,迭代器失效后,代码并不一定会崩溃,但是运行结果肯定不对,如果it不在begin和end范围内,肯定会崩溃的。
因此我们的insert和erase函数都会返回一个迭代器来供我们使用,我们修正一下上面的代码

#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v{ 1,2,3,4};//删除偶数vector<int>::iterator it = v.begin();while (it != v.end()){if ((*it) % 2 == 0){it=v.erase(it);//接受迭代器,返回的迭代器是it传入时的位置}else{it++;}}for (auto& e : v){cout << e << " ";}cout << endl;return 0;
}

我们的string其实也是一样的道理,只是对于string我们很少用迭代器
在这里插入图片描述
我们对str进行了提前扩容,造成了野指针问题,我们的string使用失效的迭代器也会崩溃

4.迭代器分类

在我们使用算法函数时,有些函数需要特定的迭代器,像我们的vector的迭代器本质就是原生指针,因此它是一个随机迭代器,我们可以看一下侯捷大佬的《STL源码剖析》里对迭代器的分类
在这里插入图片描述
在这里插入图片描述我们Forward迭代器就是单向迭代器,它是只支持重载++的迭代器,Bidrectional迭代器是双向迭代器,它支持++和–,而我们的Random是随机迭代器,它支持++和–,也支持+和-,同样支持[ ]
理论上来讲,模板语法上可以传任何类型参数,但是内部使用迭代器是有要求

🌸🌸C++STL之vector的知识大概就讲到这里啦,博主后续会继续更新更多C++的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

相关文章:

C++STL之vector(超详细)

CSTL之vector 1.vector基本介绍2.vector重要接口2.1.构造函数2.2.迭代器2.3.空间2.3.1.resize2.3.2.capacity 2.4.增删查找 3.迭代器失效4.迭代器分类 &#x1f31f;&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f68…...

ubuntu环境下安装electron环境,并快速打包

1.配置镜像源 关闭防火墙&#xff0c;命令&#xff1a;sudo ufw disable 1.1配置国内镜像源&#xff1a; vim /etc/apt/source.list deb https://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiversedeb-src https://mirrors.aliyun.com/ubuntu/ jammy main…...

【Pytorch】优化器(Optimizer)模块‘torch.optim’

torch.optim 是 PyTorch 中提供的优化器&#xff08;Optimizer&#xff09;模块&#xff0c;用于优化神经网络模型的参数&#xff0c;更新网络权重&#xff0c;使得模型在训练过程中最小化损失函数。它提供了多种常见的优化算法&#xff0c;如 梯度下降法&#xff08;SGD&#…...

API平台建设之路:从0到1的实践指南

在这个互联网蓬勃发展的时代&#xff0c;API已经成为连接各个系统、服务和应用的重要纽带。搭建一个优质的API平台不仅能为开发者提供便利&#xff0c;更能创造可观的商业价值。让我们一起探讨如何打造一个成功的API平台。 技术架构是API平台的根基。选择合适的技术栈对平台的…...

【Flink-scala】DataStream编程模型之窗口计算-触发器-驱逐器

DataStream API编程模型 1.【Flink-Scala】DataStream编程模型之数据源、数据转换、数据输出 2.【Flink-scala】DataStream编程模型之 窗口的划分-时间概念-窗口计算程序 文章目录 DataStream API编程模型前言1.触发器1.1 代码示例 2.驱逐器2.1 代码示例 总结 前言 本小节我想…...

信号灯集以及 P V 操作

一、信号灯集 1.1 信号灯集的概念 信号灯集是进程间同步的一种方式。 信号灯集创建后&#xff0c;在信号灯集内部会有很多个信号灯。 每个信号灯都可以理解为是一个信号量。 信号灯的编号是从0开始的。 比如A进程监视0号灯&#xff0c;B进程监视1号灯。 0号灯有资源&…...

在 Flutter app 中,通过视频 URL 下载视频到手机相册

在 Flutter app 中&#xff0c;通过视频 URL 下载视频到手机相册可以通过以下步骤实现&#xff1a; 1. 添加依赖 使用 dio 下载文件&#xff0c;结合 path_provider 获取临时存储路径&#xff0c;以及 gallery_saver 将文件保存到相册。 在 pubspec.yaml 中添加以下依赖&…...

Nature Methods | 人工智能在生物与医学研究中的应用

Nature Methods | 人工智能在生物与医学研究中的应用 生物研究中的深度学习 随着人工智能&#xff08;AI&#xff09;技术的迅速发展&#xff0c;尤其是深度学习和大规模预训练模型的出现&#xff0c;AI在生物学研究中的应用正在经历一场革命。从基因组学、单细胞组学到癌症生…...

Axure PR 9 随机函数 设计交互

​大家好&#xff0c;我是大明同学。 这期内容&#xff0c;我们将深入探讨Axure中随机函数的用法。 随机函数 创建随机函数所需的元件 1.打开一个新的 RP 文件并在画布上打开 Page 1。 2.在元件库中拖出一个矩形元件。 3.选中矩形元件&#xff0c;样式窗格中&#xff0c;将…...

【人工智能基础05】决策树模型

文章目录 一. 基础内容1. 决策树基本原理1.1. 定义1.2. 表示成条件概率 2. 决策树的训练算法2.1. 划分选择的算法信息增益&#xff08;ID3 算法&#xff09;信息增益比&#xff08;C4.5 算法&#xff09;基尼指数&#xff08;CART 算法&#xff09;举例说明&#xff1a;计算各个…...

【人工智能基础03】机器学习(练习题)

文章目录 课本习题监督学习的例子过拟合和欠拟合常见损失函数&#xff0c;判断一个损失函数的好坏无监督分类&#xff1a;kmeans无监督分类&#xff0c;Kmeans 三分类问题变换距离函数选择不同的起始点 重点回顾1. 监督学习、半监督学习和无监督学习的定义2. 判断学习场景3. 监…...

HarmonyOS(60)性能优化之状态管理最佳实践

状态管理最佳实践 1、避免在循环中访问状态变量1.1 反例1.2 正例 2、避免不必要的状态变量的使用3、建议使用临时变量替换状态变量3.1 反例3.2 正例 4、参考资料 1、避免在循环中访问状态变量 在应用开发中&#xff0c;应避免在循环逻辑中频繁读取状态变量&#xff0c;而是应该…...

数据库课程设计报告 超市会员管理系统

一、系统简介 1.1设计背景 受到科学技术的推动&#xff0c;全球计算机的软硬件技术迅速发展&#xff0c;以计算机为基础支撑的信息化如今已成为现代企业的一个重要标志与衡量企业综合实力的重要标准&#xff0c;并且正在悄无声息的影响与改变着国内外广泛的中小型企业的运营模…...

C++算法练习-day54——39.组合总和

题目来源&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目思路分析 题目&#xff1a;给定一个整数数组 candidates 和一个目标数 target&#xff0c;找出所有独特的组合&#xff0c;这些组合中的数字之和等于 target。每个数字在每个组合中只能使用一次。 思路&a…...

计算机毕业设计PySpark+Hadoop中国城市交通分析与预测 Python交通预测 Python交通可视化 客流量预测 交通大数据 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

Linux的文件系统

这里写目录标题 一.文件系统的基本组成索引节点目录项文件数据的存储扇区三个存储区域 二.虚拟文件系统文件系统分类进程文件表读写过程 三.文件的存储连续空间存放方式缺点 非连续空间存放方式链表方式隐式链表缺点显示链接 索引数据库缺陷索引的方式优点&#xff1a;多级索引…...

【Vue3】从零开始创建一个VUE项目

【Vue3】从零开始创建一个VUE项目 手动创建VUE项目附录 package.json文件报错处理: Failed to get response from https://registry.npmjs.org/vue-cli-version-marker 相关链接&#xff1a; 【VUE3】【Naive UI】&#xff1c;NCard&#xff1e; 标签 【VUE3】【Naive UI】&…...

9)语法分析:半倒装和全倒装

在英语中&#xff0c;倒装是一种特殊的句子结构&#xff0c;其中主语和谓语&#xff08;或助动词&#xff09;的位置被颠倒。倒装分为部分倒装和全倒装两种类型&#xff0c;它们的主要区别在于倒装的程度和使用的场合。 1. 部分倒装 (Partial Inversion) 部分倒装是指将助动词…...

Scala关于成绩的常规操作

score.txt中的数据&#xff1a; 姓名&#xff0c;语文&#xff0c;数学&#xff0c;英语 张伟&#xff0c;87&#xff0c;92&#xff0c;88 李娜&#xff0c;90&#xff0c;85&#xff0c;95 王强&#xff0c;78&#xff0c;90&#xff0c;82 赵敏&#xff0c;92&#xff0c;8…...

使用Java实现度分秒坐标转十进制度的实践

目录 前言 一、度分秒的使用场景 1、表示方法 2、两者的转换方法 3、区别及使用场景 二、Java代码转换的实现 1、确定计算值的符号 2、数值的清洗 3、度分秒转换 4、转换实例 三、总结 前言 在地理信息系统&#xff08;GIS&#xff09;、导航、测绘等领域&#xff0c…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...