手撕STL——vector
目录
引言
1,了解 STL 中的 vector
2,先来一个简易版跑起来
2_1,构造函数
2_2,扩容reserve()
2_3,push_back()
2_4,pop_back()
2_5,测试一下
3,迭代器
3_1,如何设计iterator
3_2,begin(),end()一锅端
4,功能完善
4_1,operator[ ]()
4_2,size() 和 capacity()
4_3,resize(size_t n, T x = T())
4_4,insert()
4_5,erase()
4_6,构造函数重载——迭代器
4_7,拷贝构造函数
4_8,赋值运算符重载
4_9,析构函数
5,总结
革命尚未成功,同志仍须努力
引言
上一期我们手撕了list,这一期我们就来手撕一个vector(代码在最后),vector手撕起来就比list简单很多啦。
1,了解 STL 中的 vector
在学习初阶数据结构的时候,顺序表咱们也撕过好多次了,有静态的,也有动态的,在STL中,vector是一个动态开辟的顺序表,但是它与咱们在数据结构阶段实现的顺序表是有差异的,在数据结构阶段实现的顺序表中,我们是通过 typename* a, int size, int capacity,作为成员变量
#define typename intstruct node
{typename* a;int size;int capacity;
}
但是哈,在vector中,就变得不一样啦。
template <typename T>
class vector
{private:T* _start;T* _finish;T* _end_of_storage;
}
STL 中的 vector,用了三个指针当成员变量,为什么要这样设计呢?
在C中,咱们用的是,struct,struct的成员变量咱们是可以直接访问的,但是在C++的class中,为了保护成员变量,咱们将其设置成private成员,咱们在外面是不能直接访问的,vector中有size()和capacity()函数,来获取size和capacity。但是其他的思路大致是不变的,那咱们就开始手撕吧。
2,先来一个简易版跑起来
2_1,构造函数
2_2,扩容reserve()
vector中数据是存在一段连续的空间,不能像list那样插入前new一个空间出来,我们必须提前开好空间,保证插入数据的时候空间一个是足够的。
reserve的实现过程很简单,在数据结构初阶阶段我们用realloc进行扩容,其大致原理就是,如果这段连续的空间后面的空间够就直接原地扩容,如果不够就找一个空间够的地方,重新开辟空间,并将原有的数据拷贝过去,最后将原有的空间释放。
我们直接用new和delete进行异地扩容,开辟好空间后再进行数据拷贝,拷贝完数据记得释放原来的空间,避免内存泄漏。
2_3,push_back()
因为顺序表头插需要挪动数据,代价是比较大的,STL中的vector也没有提供头插接口,所以这里只来一个头插
尾插分3步
1,检查需不需要扩容
2,将 _finish 位置赋值
3,++finish
2_4,pop_back()
尾删就比较简单啦,直接 --_finish,就可以了
2_5,测试一下
咱们目前还没有完成其他的函数,为了测试,咱们写一个打印函数print()
ok,没有问题,是可以跑起来了的。
3,迭代器
3_1,如何设计iterator
迭代器在STL中是一个非常重要的设计,它观察STL,当然在vector中的迭代器是比较简单的。
因为vector中的数据是存储在一段连续的空间中,咱们的iterator就可以直接由指针typedef得来。
typedef T* iterator;
typedef const T* const_iterator;
3_2,begin(),end()一锅端
4,功能完善
4_1,operator[ ]()
中括号重载是一个比较重要的函数,有他的存在我们就能很方便的插入修改数据。
4_2,size() 和 capacity()
直接用指针相减的中间元素个数的知识实现
4_3,resize(size_t n, T x = T())
resize()的功能大家一定要清楚,他的注意功能是改变size。
如果 n < size() 就直接删除数据,通过改变 _finish 实现
如果 size() < n < capacity (),改变size,并进行初始化
如果 capacity () < n,先开空间,在改变size,并进行初始化
4_4,insert()
insert 大致分三步
1,检查是否需要扩容
2,挪动数据
3,插入
这里要注意一个问题,当我们进行扩容后,原来的迭代器所指向的位置已经被delete清理了,这时候的iterator实际上是一个野指针。
为了防止出错,我们要在最开始通过指针的减法记录迭代器的位置,后面通过加法还原迭代器。
4_5,erase()
这里也用注意迭代器失效的问题
虽然我们这里没有扩容,进行删除后,迭代器仍然指向原来的位置
但是还是会有一点点风险,为了确保万无一失,咱们这里还是进行了存储迭代器位置,还原迭代器的操作。
4_6,构造函数重载——迭代器
在STL中,我们常可以看见用迭代器去构造一个容器,vector当然也可以,咱们就来实现一下
其实也是比较简单啊,通过迭代器,我们可以变量它,得到它的数据,再通过push_back()插入,遍历完了之后,vector也构造完了。为了可以使所有的迭代器都可以对其进行传参构造,这里还需要用到模板。
4_7,拷贝构造函数
根据参数直接构造。
先根据 被拷贝的对象 的 capacity 对要拷贝的对象进行扩容,再进行遍历和赋值。
4_8,赋值运算符重载
还是有传统写法与现代写法。
传统写法是 遍历参数的数据 给需要被赋值的对象进行数据的赋值
咱们这里写现代写法。
传参的时候不传引用,编译器根据咱们的拷贝构造函数进行拷贝,使用swap函数进行交换,对于参数 x 而言,它的数据存储的空间再堆上,但是x的三个成员变量会在赋值运算符重载这个函数结束的时候进行空间的回收,但是在堆的那一部分数据还是存在的。
使用 swap 函数进行交互 只是交换了 参数 x 和 待赋值的对象的三个指针,让待赋值的对象的三个成员遍历指向堆存储的数据的位置。
传统写法和现代写法原理大差不差的,只不过现代写法把拷贝数据的工作交给了编译器,实现起来更为简洁
4_9,析构函数
因为vector的数据存储在一段连续的区域,直接delete就可以了
5,总结
虽然咱们手撕了一个 vector 但是 咱们撕的只能说是一个简易版,我只是把 vector 里面常用,经典的函数带着大家手撕了一下,库里面的 vector的功能是非常强大的,而且大多函数都有多种重载。
大家可以通过这篇博客感受一下vector 的创建,也可以继续完善咱们自己的vector
革命尚未成功,同志仍须努力
#pragma once
#include <assert.h>
#include <iostream>
namespace ssy
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;vector(): _start(nullptr), _finish(nullptr), _end_of_storage(nullptr){}vector(size_t n, T data = T()): _start(nullptr), _finish(nullptr), _end_of_storage(nullptr){resize(n, data);}template<class InputIterator>vector(InputIterator first, InputIterator last): _start(nullptr), _finish(nullptr), _end_of_storage(nullptr){while (first != last){push_back(*first);++first;}}vector(const vector<int>& v): _start(nullptr), _finish(nullptr), _end_of_storage(nullptr){_start = new T[v.capacity()];size_t sz = v.size();for (int i = 0; i < sz; i++){_start[i] = v._start[i];}_finish = _start + sz;_end_of_storage = _start + v.capacity();}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}vector<T>& operator=(const vector<T> x){swap(x);return *this;}~vector(){if (_start){delete _start;_start = _finish = _end_of_storage = nullptr;}}size_t size(){return _finish - _start;}size_t capacity(){return _end_of_storage - _start;}void resize(size_t n, T data = T()){size_t sz = size();if (n < capacity()){_finish = _start + n;for (int i = sz; i < n; i++){_start[i] = data;}}else{reserve(n);for (int i = sz; i < n; i++){_start[i] = data;}_finish = _start + n;}}void reserve(size_t n){if (n > capacity()){T* tmp = new T[n];int size = _finish - _start;if (_start){for (int i = 0; i < size; i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + size;_end_of_storage = _start + n;}}void push_back(const T& x){if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = x;++_finish;}void pop_back(){--_finish;}T& operator[](size_t pos){assert(pos < capacity());return _start[pos];}const T& operator[](size_t pos) const{assert(pos < capacity());return _start[pos];}iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}iterator insert(iterator pos, const T& data){size_t ppos = pos - _start;assert(ppos <= size());if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : 2 * capacity());}size_t end = size();while (end > ppos){_start[end] = _start[end - 1];--end;}_start[end] = data;++_finish;return _start + ppos;}iterator erase(iterator pos){size_t ppos = pos - _start;assert(ppos < size());size_t len = ppos;size_t end = size();while (ppos < end){_start[ppos] = _start[ppos + 1];ppos++;}--_finish;return _start + len;}void print(){int n = _finish - _start;for (int i = 0; i < n; i++){cout << _start[i] << " ";}cout << endl;}private:T* _start;T* _finish;T* _end_of_storage;};
}
相关文章:
手撕STL——vector
目录 引言 1,了解 STL 中的 vector 2,先来一个简易版跑起来 2_1,构造函数 2_2,扩容reserve() 2_3,push_back() 2_4,pop_back() …...
新书速览|DeepSeek移动端AI应用开发:基于Android与iOS
《DeepSeek移动端AI应用开发:基于Android与iOS》 1 本书内容 《DeepSeek移动端AI应用开发:基于Android与iOS》深入剖析了DeepSeek平台的架构原理、API调用及开发实践等核心内容,助力读者在Android与iOS移动端高效集成DeepSeek API,打造出契…...
详解STM32时基单元中参数 TIM_ClockDivision 的含义
在 STM32 定时器时基单元配置中,TIM_TimeBaseInitStruct->TIM_ClockDivision 用于设置 定时器时钟的分频系数,主要影响 输入捕获滤波器 和 输出比较同步信号 的时钟分割。以下是其核心作用、参数含义及应用场景的详细解析: 一、核心作用&…...
黑马V11版 最新Java高级软件工程师课程-JavaEE精英进阶课
课程大小:60.2G 课程下载:https://download.csdn.net/download/m0_66047725/90615581 更多资源下载:关注我 阶段一 中台战略与组件化开发专题课程 阶段二 【物流行业】品达物流TMS 阶段三 智牛股 阶段四 千亿级电商秒杀解决方案专题 …...
【Win】 cmd 执行curl命令时,输出 ‘命令管道位置 1 的 cmdlet Invoke-WebRequest 请为以下参数提供值: Uri: ’ ?
1.原因: 有一个名为 Invoke-WebRequest 的 CmdLet,其别名为 curl。因此,当您执行此命令时,它会尝试使用 Invoke-WebRequest,而不是使用 curl。 2.解决办法 在cmd中输入如下命令删除这个curl别名: Remov…...
【k8s系列4】工具介绍
1、虚拟机软件 vmware workstation 2、shell 软件 MobaXterm 3、centos7.9 下载地址 (https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/?spma2c6h.25603864.0.0.374bf5adOaiFPW) 4、上网软件...
设计模式 --- 装饰器模式
装饰模式是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。 优点: 1.灵…...
docker.desktop下安装普罗米修斯prometheus、grafana并看服务器信息
目标 在docker.desktop下先安装这三种组件,然后显示当前服务的CPU等指标。各种坑已踩,用的是当前时间最新的镜像 核心关系概述 组件角色依赖关系Prometheus开源监控系统,负责 数据采集、存储、查询及告警。依赖 Node-Exporter 提供的指标数据。Node-Exporter专用的 数据采集…...
学习设计模式《二》——外观模式
一、基础概念 1.1、外观模式的简介 外观模式的本质是【封装交互、简化调用】; 外观模式的说明:就是通过引入一个外观类,在这个类里面定义客户端想要的简单方法,然后在这些方法里面实现;由外观类再去分别调用内部的多个…...
python中,处理多分类时,模型之间的参数设置
在Python的机器学习库中,处理多分类问题时,不同的模型可能会有不同的参数设置来适应多分类场景。这里列举几个常见模型及相关的多分类参数: 1. Logistic Regression (逻辑回归) 在Scikit-Learn库中,逻辑回归模型可以通过设置mul…...
2025年03月中国电子学会青少年软件编程(Python)等级考试试卷(四级)真题
青少年软件编程(Python)等级考试试卷(四级) 分数:100 题数:38 答案解析:https://blog.csdn.net/qq_33897084/article/details/147341407 一、单选题(共25题,共50分) 1. 下列程序段…...
蓝桥杯12. 日期问题
日期问题 原题目链接 题目描述 小明正在整理一批历史文献。这些历史文献中出现了很多日期。 小明知道这些日期都在 1960 年 1 月 1 日 至 2059 年 12 月 31 日 之间。 令小明头疼的是,这些日期采用的格式非常不统一: 有的采用 年/月/日有的采用 月…...
【MATLAB代码例程】AOA与TOA结合的高精度平面地位,适用于四个基站的情况,附完整的代码
本代码实现了一种基于到达角(AOA) 和到达时间(TOA) 的混合定位算法,适用于二维平面内移动或静止目标的定位。通过4个基站的协同测量,结合最小二乘法和几何解算,能够有效估计目标位置,并支持噪声模拟、误差分析和可视化输出。适用于室内定位、无人机导航、工业监测等场景…...
ARINC818协议(五)
1.R_CTL,设置固定的0x44即可 2.Dest_ID:目的地D_ID,如果不需要目的地址,就设置为0;ADVB协议支持 多个视频目的地址,广播通信; 3.cs_ctl在FC-AV上不用 4.source_ID:S_ID [23:0]包含源实体的端口的地址标识;不用就设置为0. ADVB允许…...
国产品牌芯洲科技100V降压芯片系列
SCT2A25采用带集成环路补偿的恒导通时间(COT)模式控制,大大简化了转换器的片外配置。SCT2A25具有典型的140uA低静态电流,采用脉冲频率调制(PFM)模式,它使转换器在轻载或空载条件下实现高转换效率。 芯洲科技100V降压芯片系列提供丰富的48V系…...
遨游科普:三防平板除了三防特性?还能实现什么功能?
在工业4.0浪潮席卷全球的今天,电子设备的功能边界正经历着革命性突破。三防平板电脑作为"危、急、特"场景的智能终端代表,其价值早已超越防水、防尘、防摔的基础防护属性。遨游通讯通过系统级技术创新,将三防平板打造为集通信中枢、…...
边缘计算网关组态功能的定义
边缘计算网关组态功能的定义 边缘计算网关组态是指根据特定的应用场景和需求,对边缘计算网关进行配置和定制的过程。它涵盖了硬件接口的选择、软件功能的设定、通信协议的配置以及数据处理流程的设计等多个方面,旨在使网关设备更加贴合实际应用场景&…...
数据可视化笔记:柱状图
数据可视化笔记:柱状图与饼图 1.1 一、基础配置 在进行数据可视化之前,需要对Matplotlib进行一些基础配置,以确保图表能够正确显示中文以及设置合适的分辨率和大小。 from matplotlib import pyplot as plt import numpy as np# 设置中文字…...
珈和科技:无人机技术赋能智慧农业,精准施肥与病虫害监控全面升级
无人机技术在农业领域的兴起,是现代技术发展为传统农业带来的重要变革。目前, 无人机已成为农业生产中不可或缺的关键工具,在提高粮食产量、改善土壤健康和保护生态环境等方面提供了新的解决方案。珈和科技从无人机的类型、特点和监测系统入手…...
UR5e机器人动力学
机器人动力学研究力与运动之间的关系,核心目标是建立关节力矩与关节位置、速度、加速度的数学关系。动力学模型通常分为: 正向动力学:已知关节力矩,计算末端执行器的运动(加速度)。 逆向动力学:已知期望的运动(位置、速度、加速度),计算所需的关节力矩。 https://www…...
【go】什么是Go语言的GPM模型?工作流程?为什么Go语言中的GMP模型需要有P?
Go语言GMP调度模型详解 一、GMP模型核心概念 Go语言的GMP模型是一种高效的轻量级线程管理调度系统,由三个核心组件构成: G (Goroutine): 轻量级协程,初始栈仅2KB(可动态扩容)用户态调度,创建成…...
X-AnyLabeling开源程序借助 Segment Anything 和其他出色模型的 AI 支持轻松进行数据标记。
一、软件介绍 文末提供源码和程序下载学习 使用 X-AnyLabeling开源程序可以 导入、管理和保存数据。用户可以通过多种方式导入图像和视频文件,包括快捷方式或菜单选项。此外,它还涵盖数据删除、图像切换以及标签和图像数据的保存,以确保高效…...
简易 Python 爬虫实现,10min可完成带效果源码
目录 准备工作 编写爬虫代码 运行爬虫 查看结果 遇到的问题及解决 总结 前言和效果 本文记录了使用 Python 实现一个简单网页爬虫的过程,目标是爬取 quotes.toscrape.com 的名言和作者,并将结果保存到文本文件。以下是完整步骤,包含环境…...
全志H5,NanopiKP1lus移植QT5.12记录
移植步骤 机器环境下载QT5.12.0源码安装交叉编译器修改qmake.conf文件配置编译选项qt5的configure选项说明基本配置选项编译器和链接器选项功能模块配置第三方库集成注意事项 配置过程报错解决配置完成编译过程报错解决编译完成将arm-qt文件夹传送到开发板配置板子环境变量运行…...
Spring Boot 依赖注入与Bean管理:JavaConfig如何取代XML?
大家好呀!今天我们来聊一个超级实用的技术话题 —— Spring Boot 中的依赖注入和Bean管理,特别是JavaConfig是如何一步步取代XML配置的。我知道很多小伙伴一听到"依赖注入"、"Bean管理"这些词就头大,别担心!我…...
AUTOSAR图解==>AUTOSAR_SWS_E2ETransformer
AUTOSAR E2E Transformer详解 基于AUTOSAR标准的端到端通信保护变换器技术解析 目录 1. E2E Transformer概述 1.1 E2E Transformer的作用1.2 功能特点1.3 应用场景限制 2. 模块架构 2.1 架构设计2.2 与其他模块的关系 3. 初始化与状态机 3.1 模块状态流转3.2 初始化与去初始化…...
从Archery到NineData:积加科技驱动数据库研发效能与数据安全双升级
积加科技作为国内领先的企业级数字化解决方案服务商,依托自研的 A4X 数字化平台(https://a4x.io/),专注于为全球范围内的视觉物联网(IoT)设备提供 PaaS/SaaS 服务。致力于运用 AI 技术赋能物联网世界的各类…...
hadoop和Yarn的基本介绍
Hadoop的三大结构及各自作用? Hadoop是一个由Apache基金会开发的分布式系统基础架构,主要用于处理大规模数据集的分布式存储和计算。Hadoop的三大核心结构是HDFS(Hadoop Distributed File System)、MapReduce和YARN(Y…...
神经接口安全攻防:从技术漏洞到伦理挑战
随着脑机接口(BCI)技术的快速发展,神经接口设备已从实验室走向消费市场。然而,2025年曝光的某品牌脑机接口设备漏洞(CVE-2025-3278)引发了行业对神经数据安全的深度反思。本文围绕神经接口安全的核心矛盾&a…...
云轴科技ZStack入选中国人工智能产业发展联盟《大模型应用交付供应商名录》
2025年4月8日至9日,中国人工智能产业发展联盟(以下简称AIIA)第十四次全体会议暨人工智能赋能新型工业化深度行(南京站)在南京召开。工业和信息化部科技司副司长杜广达,中国信息通信研究院院长、中国人工智能…...
SpringBoot项目异常处理
一、异常问题描述 进行添加员工测试的时候,服务端报错, 报错信息如下: java.sql.SQLIntegrityConstraintViolationException:主要就是因为在 employee 表结构中,我们针对于username字段,建立了唯一索引,添…...
机器学习05-CNN
CNN(卷积神经网络)学习文档 一、引言 卷积神经网络(Convolutional Neural Network,CNN)是深度学习中的一种重要网络结构,在图像识别、计算机视觉等领域取得了巨大成功。CNN 的设计灵感来源于生物视觉系统…...
Java Web 之 Servlet 100问
Filter 是什么? 在Java Web开发中,Filter(过滤器)是一种用于在请求到达目标资源(如Servlet、JSP)之前或响应返回客户端之前进行预处理和后处理的组件。Filter可以拦截请求和响应,执行特定的操作…...
z-library电子图书馆最新地址的查询方法
对于喜欢读书的伙伴们,应该都听说过z站(z-library),优点多多,缺点就是地址不稳定,经常会变化网站地址。然后我最近发现了一个工具,可以不间断更新官方可用的z站地址:电子书最新地址...
PyCharm入门导览
一、项目视图 项目视图位置如下所示: 项目视图是主要工具窗口之一。它包含项目目录、SDK特定的外部库和临时文件。点击带条纹的按 钮可以预览演示项目。也可以按Alt 1 打开。 二、Python解释器 点击右下角项目的名字,可以快速进入【Python解释器】界面…...
算法题(127):最大子段和
审题: 本题需要我们找到n个整数中连续且非空的最大子段和 思路: 方法一:前缀和 我们的思路是将每个索引位置的最大子段和求出,然后用answer进行max维护,最后输出answer即可 最大子段和怎么求? 子段和 f[i]…...
物联网分层架构全解析:从感知到应用的智能生态构建
物联网分层架构一般可细分为感知层、网络层、平台层和应用层,以下是各层更详细的介绍: 一、感知层 1.功能 数据采集:利用各类传感器对物理世界的各种信息进行采集,包括环境参数(如温度、湿度、光照、气压等…...
系统架构师2025年论文通用模板
搭建自己的模板 1、项目选择与实施建议整理 一、项目选择标准 金额与周期要求:优先选择金额在 200万以上 的中大型商业项目,研发周期建议 不少于8个月。避免选择小型项目(如金额低于100万、周期短于1年)。 …...
Flink 2.0 编译
文章目录 Flink 2.0 编译第一个问题 java 版本太低maven 版本太低maven 版本太高开始编译扩展多版本jdk 配置 Flink 2.0 编译 看到Flink2.0 出来了,想去玩玩,看看怎么样,当然第一件事,就是编译代码,但是没想到这么多问…...
Java线程的几种状态
线程状态我们在此介绍六种线程状态 1.NEW 2.RUNNABLE 3.TIMED_WAITING 4.BLOCKED 5.WAITING 6.TERMINATED 1.初始状态 (NEW) 当一个线程对象被创建但尚未调用 start() 方法时,线程处于初始状态。此时,线程还没有开始执行。 通俗的讲就是安排了工作但是…...
2025年03月中国电子学会青少年软件编程(Python)等级考试试卷(一级)真题
青少年软件编程(Python)等级考试试卷(一级) 分数:100 题数:37 答案解析:https://blog.csdn.net/qq_33897084/article/details/147335019?spm1001.2014.3001.5501 一、单选题(共25题࿰…...
「数据可视化 D3系列」入门第十章:饼图绘制详解与实现
饼图绘制详解与实现 一、饼图绘制核心知识1. d3.arc() 弧形生成器2. d3.pie() 布局函数3. arc.centroid() 中心点计算4. 颜色方案 二、饼图实现代码小结核心知识点下章预告:力导向图 一、饼图绘制核心知识 1. d3.arc() 弧形生成器 功能: 生成圆形、扇形…...
三维点拟合平面ransac c++
理论 平面的一般定义 在三维空间中,一个平面可以由两个要素唯一确定: 法向量 n(a,b,c):垂直于平面的方向 平面上一点 平面上任意一点 p(x,y,z) 满足: ( p − p 0 ) ∗ n 0 (p - p0) * n 0 (p−p0)∗n0 即 a ( x − x 0 ) …...
第六章:6.6输入以下的杨辉三角形,要求输出10行
//输入以下的杨辉三角形,要求输出10行 #include<stdio.h> int main() {int a[10][10] { 0 };int i 0, j 0;for (i 0; i < 10; i){for (j 0; j < 10; j){if (j 0){a[i][j] 1;}else if (i j){a[i][j] 1;}else{a[i][j] a[i - 1][j - 1] a[i - …...
初识Redis · C++客户端string
目录 前言: string的API使用 set get: expire: NX XX: mset,mget: getrange setrange: incr decr 前言: 在前文,我们已经学习了Redis的定制化客户端怎么来的,以及如何配置好Redis定制化客户端&…...
React 事件处理基础
React 中最常见的两个需求,一个是列表渲染,另一个就是绑定点击事件。 这一篇就是从最基础的按钮点击开始,分四个阶段,逐步理解 React 中事件的写法和参数传递方式。 📍阶段一:最简单的点击事件 function A…...
插入排序和希尔排序
今天给小伙伴们分享两个比较基础的排序算法,插入排序和希尔排序,这两个排序算法之间联系还是挺多的,所以放在一起。希尔排序可以看作是插入排序的升级版,在面对一些更为复杂的场景时,希尔排序的效率往往要比插入排序高…...
Model Context Protocol (MCP) 开放协议对医疗多模态数据整合的分析路径【附代码】
Model Context Protocol (MCP) 作为一种革命性的开放协议,正在重塑医疗领域多模态数据整合的方式。本文将深入分析MCP协议在医疗多模态数据整合中的具体路径、技术实现、应用场景及未来发展方向,揭示这一协议如何成为连接AI与医疗数据的关键桥梁。 MCP协议概述及其在医疗多模…...
Oracle 11g通过dg4odbc配置dblink连接PostgreSQL
1、安装unixodbc 2、安装postgresql yum install -y postgresql17-odbc 3、配置postgresqlodbc数据源 vim /usr/local/etc/odbcinst.ini##添加如下 [mypg] Driver /usr/lib64/psqlodbcw.so Servername localhost Port 5432 Database postgres Username postgres Pas…...
docker 安装prometheus普罗米修斯
prometheus(普罗米修斯):天生为采集存储监控数据而生的时序数据库。prometheus通过各种Exporter采集到监控数据,然后存储进prometheus中,以供查询展示 grafana:一个监控仪表系统。grafana的数据来源可以有…...