C++ 之 【模拟实现 list(节点、迭代器、常见接口)】(将三个模板放在同一个命名空间就实现 list 啦)
1.前提准备
(1) list 的底层结构一般是带头双向循环链表
(1)为避免命名冲突,需要创建一个命名空间来存放模拟实现的 list
(2)下面模拟实现list时,声明和定义不分离(具体原因后续讲解)
2.完整实现
2.1 链表节点
template<class T>//节点写成类模板,适合不同的数据类型
struct __list_node//带头双向循环链表的节点,因为下面会使用,用struct
{typedef __list_node<T> Node;//起个别名,谨防忘记实例化(即指定参数)Node* _next;Node* _prev;T _val;__list_node(const T& val = T()):_next(nullptr),_prev(nullptr),_val(val){}
};
(1)将链表节点写成一个类模板,将数据类型指定为模板参数T,以支持不同类型的数据
(2)使用 struct 定义节点类,原因有二
1.后续所实现的链表,迭代器需要用到节点,使用 struct 方便暴露节点成员
2.用户使用链表时,并不知晓节点的名称等消息,强行使用而出错的锅不用实现者背
(3)不要将类模板名直接写为node,因为后续还有树等数据结构也有节点,
所以命名时通常加 list 前缀来区分
(1)节点包含指向前后的两个指针,指针类型是节点类型,注意
类模板中,__list_node是类模板名,__list_node<T>是类型
谨防忘记,为类型起个别名
typedef __list_node<T> Node;//起个别名,谨防忘记实例化(即指定参数)Node* _next;Node* _prev;
(2)节点初始化,将指针置空,数据依用户传递为主,缺省值为辅
__list_node(const T& val = T()):_next(nullptr),_prev(nullptr),_val(val){}
(1)后续实现链表时才会在堆上申请节点
节点内部并没有申请其他资源,就没必要在节点中写析构函数等其他默认成员函数
等链表使用完毕,再在链表中进行资源释放即可
2.2 链表中的迭代器
迭代器可以被理解为 抽象化的指针,它模拟指针的行为(遍历和操作元素),
使用方式与指针一致,但它的适用范围更广
(1)vector是动态顺序表,内存连续分布,指针可以遍历和操作元素
所以在vector中,指针就是一种迭代器
但是 list 的内存分布一般不连续,节点指针不可以遍历和操作元素,
所以,我们定义一个迭代器类来封装节点指针,通过运算符重载来模拟指针的行为,
此时,该迭代器类的对象就是链表的迭代器
template<class T, class Ref, class Ptr>//节点指针类型是__list_node<T>*struct __list_iterator//list中需要使用迭代器,使用struct供下面使用{typedef __list_node<T> Node;typedef __list_iterator<T, Ref, Ptr> Self;Node* _node;//用节点指针构造迭代器__list_iterator(Node* node):_node(node){}//it1 != it2bool operator!=(const Self& it)const{return _node != it._node;}bool operator==(const Self& it)const{return _node == it._node;}//*Ref operator*()const//Ref是引用的意思,用来控制普通迭代器与const迭代器{return _node->_val;}Self& operator++(){_node = _node->_next;return *this;}Self operator++(int){iterator temp(*this);_node = _node->_next;return temp;}Self& operator--(){_node = _node->_prev;return *this;}Self operator--(int){Self temp(*this);_node = _node->_prev;return temp;}Ptr operator->()const{return &(_node->_val);}};
2.2.1 迭代器的细节点
迭代器类的成员变量就是节点指针
(1)节点类型为:__list_node<类型>,为了支持不同类型的数据,将类型指定为参数T,
同时为了简便,为节点起个别名 Node
typedef __list_node<T> Node;
所以指针类型就是 Node*,
Node* _node;//用节点指针构造迭代器
(1)使用 struct 定义迭代器类,原因有二
1.后续所实现的链表中的常用接口需要用到迭代器,使用struct暴露成员直接供其使用
2.用户使用链表时,并未知晓迭代器的完整信息,强行使用而导致出错的锅不用实现者背
(2)命名迭代器类时通常加 list 前缀来区分
(3)迭代器对象名字太长,起个别名Self,self 就是 自己的意思
typedef __list_iterator<T, Ref, Ptr> Self;
2.2.2 迭代器的构造函数
__list_iterator(Node* node):_node(node)
{}
(1)后续实现链表时,显示传递一个节点指针以构造一个迭代器
(2)迭代器内部并没有申请其他资源,就没必要在迭代器类中写析构函数等其他默认成员函数
2.2.3 迭代器间的比较
bool operator!=(const Self& it)
{return _node != it._node;
}bool operator==(const Self& it)
{return _node == it._node;
}
(1)迭代器之间的比较实际上就是 节点指针之间的比较,运算符重载即可
2.2.4 迭代器访问数据
Ref operator*()//Ref是引用的意思,用来控制普通迭代器与const迭代器
{return _node->_val;
}
(1)指针解引用可以访问到它所指向的数据,迭代器模拟指针
通过运算符重载,使得解引用迭代器就是 获取 节点指针指向的数据
(2)Ref是引用的意思,用来控制普通迭代器与const迭代器,下面来仔细讲解
2.2.5 普通迭代器与const迭代器的主要区别
不加const修饰的链表包含的是 普通迭代器,const 修饰的链表包含的是 const迭代器。
不加const修饰的链表中,节点的数据可以被修改,const 修饰的链表则相反
所以普通迭代器与const迭代器的主要区别就是,二者访问数据的权限间的区别
普通迭代器 可读可修改数据, const 迭代器 只可读 数据
Ref operator*()//Ref是引用的意思,用来控制普通迭代器与const迭代器
{return _node->_val;
}
所以,将解引用返回值类型指定为模板参数
后续通过显示传递不同解引用返回值类型(T&, const T&)(T为数据类型),
就可以实现普通迭代器和const迭代器
2.2.6 迭代器的遍历
Self& operator++()
{_node = _node->_next;return *this;
}Self operator++(int)
{iterator temp(*this);_node = _node->_next;return temp;
}Self& operator--()
{_node = _node->_prev;return *this;
}Self operator--(int)
{Self temp(*this);_node = _node->_prev;return temp;
}
(1)前置++,重载运算符,让节点指针指向后一个节点,同时返回自己的引用即可
(2)后置++,重载运算符,让节点指针指向后一个节点,同时返回自己的拷贝即可
(1)前置--,重载运算符,让节点指针指向前一个节点,同时返回自己的引用即可
(2)后置--,重载运算符,让节点指针指向前一个节点,同时返回自己的拷贝即可
2.2.7 重载 -> 运算符
Ptr operator->()const
{return &(_node->_val);
}
struct A {int _a1;int _a2;A(int a1 = 0, int a2 = 0):_a1(a1),_a2(a2){} }; void test_list2() {list<A> lt;lt.push_back(A(1, 1));lt.push_back(A(2, 2));lt.push_back(A(3, 3));lt.push_back(A(4, 4));list<A>::iterator it = lt.begin();while (it != lt.end()){//cout << (*it)._a1 << ' ' << (*it)._a2 << endl;cout << it->_a1 << ' ' << it->_a2 << endl;//it->->_a1有省略++it;}cout << endl; }
当节点存储的是一个自定义类型的数据的时候,想要访问自定义类型的数据有两个方法
//cout << (*it)._a1 << ' ' << (*it)._a2 << endl; cout << it->_a1 << ' ' << it->_a2 << endl;//it->->_a1有省略
(1)解引用迭代器:
(*it)._a1
,通过operator*
获取对象,再用.
操作符访问成员。(2)调用
operator->
:it->_a1
,通过operator->
获取对象的指针(或类指针对象),再用
->
访问成员cout << it->_a1 << ' ' << it->_a2 << endl;//it->->_a1有省略
虽然访问数据时省略了一个 ->
但是这行代码是能正常运行并访问数据的,实际上,为了简洁,迭代器访问自定义类型的数据时,只需要一个->即可,你可以认为编译器能够自动识别并补充这里的省略
重载->运算符返回的是自定义类型对象的地址(用指针接收),
将指针类型指定为模板参数Ptr,
后续通过显示传递不同解引用返回值类型(T*, const T*)(T为数据类型),
就可以实现普通迭代器和const迭代器
2.3 链表中的常见接口
template<class T>class list{typedef __list_node<T> Node;public:typedef __list_iterator<T, T&, T*> iterator;//迭代器需要放到外面使用,所以别名也要在public中typedef __list_iterator<T, const T&, const T*> const_iterator;//迭代器需要放到外面使用,所以别名也要在public中iterator begin(){return _head->_next;//单参数返回,调用构造函数生成临时对象}iterator end(){return _head;}const_iterator begin()const{return _head->_next;}const_iterator end()const{return _head;}//构造函数void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_init();}//lt(lt1)list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}//lt1 = lt2void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}list<T>& operator=(list<T> lt){swap(lt);return *this;}//析构函数~list(){clear();delete _head;_head = nullptr;}void clear(){auto it = begin();while (it != end()){it = erase(it);}_size = 0;}//尾插void push_back(const T& val){先找尾//Node* tail = _head->_prev;创造尾插节点//Node* newnode = new Node(val);_head tail newnode//_head->_prev = newnode;//newnode->_next = _head;//tail->_next = newnode;//newnode->_prev = tail;insert(end(), val);}void push_front(const T& val){insert(begin(), val);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}//insert\eraseiterator insert(iterator pos, const T& val){//创建新节点Node* newnode = new Node(val);//使用结点指针而不是迭代器进行链接Node* cur = pos._node;//prev newnode curNode* prev = cur->_prev;prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;++_size;return newnode;}iterator erase(iterator pos){assert(pos != end());Node* cur = pos._node;//prev cur nextNode* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;cur = nullptr;--_size;return prev;}size_t size()const{return _size;}private:Node* _head;size_t _size;};
2.3.1 链表中的细节点
(1)链表同样是一个类模板,模板参数就是节点数据类型
(2)成员变量包含 哨兵位节点的指针_head 和 链表的大小_size (不包含头节点的节点个数)
(1)使用 class 定义 list
不同于上述的节点和迭代器, list 需要实现封装,只提供相应接口供外部使用
(1)节点类型为:__list_node<类型>,为了支持不同类型的数据,将类型指定为参数T,
同时为了简便,为节点起个别名 Node
typedef __list_node<T> Node;
注意,为了防止外部使用 Node, 需要将这行代码写在访问限定符private的作用域之内
(2)迭代器对象名字太长,为符合日常使用习惯起别名如下:
typedef __list_iterator<T, T&, T*> iterator; typedef __list_iterator<T, const T&, const T*> const_iterator;
基于上述"普通迭代器与const迭代器的区别",指定相应参数即可达到
注意,为了外部可以使用迭代器iterator,
所以需要将这行代码写在访问限定符public的作用域之内
2.3.2 链表中迭代器的接口
iterator begin(){return _head->_next;//单参数返回,调用构造函数生成临时对象}iterator end(){return _head;}const_iterator begin()const{return _head->_next;}const_iterator end()const{return _head;}
(1)begin函数返回的是指向第一个有效节点(哨兵位的下一个位置)的迭代器
函数内部直接返回相应指针即可,
因为迭代器的构造函数是单参数类型,编译器会用该指针构造出相应迭代器
(2)其他函数按要求返回相应指针即可
(3)注意,const迭代器相关函数只有const对象才能调用,所用需要用const修饰
2.3.3 链表的构造函数
//构造函数void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_init();}
(1)初始化一个链表就是创建一个头节点,使其前后指针指向自己(起到双向循环的作用),
并把链表的大小置为0的过程,将这个过程抽象为一个函数,以供后续拷贝构造函数的使用
2.3.4 insert、erase函数
iterator insert(iterator pos, const T& x){Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);prev->_next = newnode;newnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;++_size;return newnode;}
insert 通常是指 在 pos位置之前插入
(1)只实现的单元素的插入,插入位置 pos 的类型是迭代器,返回的是新插入节点的位置
(2)插入时只需要注意 插入节点,插入节点前一个节点与新节点之间的关系
因为迭代器改变指向有点麻烦,使用节点指针完成上述关系的链接
因为链表由哨兵位节点,不用考虑头插为空
(3)插入一个节点,_size++
iterator erase(iterator pos){assert(pos != end());Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;--_size;return next;}
(1)不能删除哨兵位节点,同时注意 _size--
(1)erase函数存在迭代器失效问题,返回被删除节点的下一个节点的迭代器
(2)删除时注意提前保存上一个节点和下一个节点即可
2.3.5 尾插尾删头插头删
实现好了insert、erase函数以及迭代器的接口之后,
直接调用函数即可
void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}
2.3.6 clear 与 析构函数
void clear(){iterator it = begin();while (it != end()){it = erase(it);}_size = 0;}~list(){clear();delete _head;_head = nullptr;}
(1)clear函数的作用是清理有效节点,不包含哨兵位,
直接迭代器遍历链表并删除节点即可,注意将_size 置空
(2)析构函数就是在 clear 之后, 清理头节点
2.3.7 拷贝构造函数
list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}
拷贝构造一个链表,被构造对象首先需要进行初始化,
然后遍历链表进行尾插即可
2.3.8 赋值重载函数
void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}//lt1 = lt2list<T>& operator=(list<T> lt){swap(lt);return *this;}
现代写法,不用自己开空间,直接传值传参,
lt 是 lt2 的深拷贝(拷贝构造实现的是深拷贝),然后交换两个链表,传引用返回
2.3.9 size函数
size_t size(){return _size;}
前面的insert 、erase、clear函数已经对_size变量进行了相应操作
这里直接返回即可
相关文章:
C++ 之 【模拟实现 list(节点、迭代器、常见接口)】(将三个模板放在同一个命名空间就实现 list 啦)
1.前提准备 (1) list 的底层结构一般是带头双向循环链表 (1)为避免命名冲突,需要创建一个命名空间来存放模拟实现的 list (2)下面模拟实现list时,声明和定义不分离(具体原因后续讲解) 2.完整实现 2.1 链表节点 template<class T>//节点写成类模板…...
数字图像处理 -- 眼底图像血管分割方法
算法框架 基于深度学习的 U-Net 架构,结合注意力机制(Attention Gate)与多尺度特征提取,以提高细小血管的检测能力。整体流程如下: 输入图像预处理:提取绿色通道 & CLAHE 增强数据增强:旋…...
基于ffmpeg的音视频编码
1 音频编码 本质上是由pcm文件转到一个协议文件 比如说aac协议 1.1 音频基本知识回归 比特率 比特率是指单位时间内传输或处理的比特(bit)数量,通常用 bps(bits per second,比特每秒)来表示。它是衡量数…...
Android wifi开发调试总结
Android wifi开发调试简单总结 文章目录 Android wifi开发调试简单总结一、前言二、wifi demo开发1、开关和连接2、wifi开启主要流程3 、wifi主要广播4、相关日志5、demo示例 三、其他1、Wifi开发小结2、其他wifi知识小结(1)Android无线Wifi开发…...
LLVIP、KAIST、M3FD数据集
LLVIP、KAIST、M3FD数据集 (可见光红外,双模态数据集,已配准已对齐已清洗,已处理为txt格式,YOLO可直接训练) 电子产品,一经出售,概不退换 算法设计、毕业设计、期刊专利!…...
datasets 数据处理封装后,统一处理流程以避免Dataset Map顺序依赖问题
文章目录 处理流程说明小结 在实际项目中,我们常常需要对数据集进行预处理。为了规范操作,我封装了一个基础数据集处理类: class DatasetAbstract:"""所有数据集都应包含以下几个字段:* question:用户…...
【学习笔记】机器学习(Machine Learning) | 第四章(3)| 多变量线性回归
机器学习(Machine Learning) 简要声明 基于吴恩达教授(Andrew Ng)课程视频 BiliBili课程资源 文章目录 机器学习(Machine Learning)简要声明 三、特征工程与多项式回归(一)特征工程:从数据中发…...
将本地Springboot项目部署到Linux服务器
1、打包后端项目 在IDEA的终端上执行命令 mvn clean package "-Dmaven.test.skiptrue" 在target目录下查看jar包是否存在 2、idea运行jar包(可选) 在IDEA的终端上执行命令 # 进入jar包所在目录 E:\LzpWorkspaces\lzp-records> cd .\tar…...
无人设备遥控器之实时数据保护技术篇
无人设备遥控器的实时数据保护技术是保障设备安全运行、避免信息泄露或恶意干扰的核心手段,其核心目标是在复杂电磁环境和网络攻击威胁下,确保指令传输的完整性、保密性和抗干扰性。 一、技术实现路径 链路层加密与认证 动态密钥协商:采用…...
【优秀三方库研读】【性能优化点滴】odygrd/quill 解决伪共享
一、伪共享(False Sharing)问题本质 当不同CPU核心频繁修改**同一缓存行(Cache Line)**中的不同变量时,会导致严重的性能下降。现代CPU的缓存系统以缓存行(通常64字节)为单位操作内存ÿ…...
JavaScript性能优化实战(6):网络请求与资源加载优化
引言 在现代Web应用开发中,网络性能已成为影响用户体验的关键因素。据统计,用户等待页面加载的耐心通常不超过3秒,超过这个时间,约40%的用户会选择离开。此外,Google的研究表明,页面加载时间每增加0.5秒,流量就会下降约20%。因此,优化网络请求和资源加载不仅关乎用户体…...
re题(49)BUUCTF-crackMe
BUUCTF在线评测 int wmain() {FILE *v0; // eaxFILE *v1; // eaxchar v3; // [esp3h] [ebp-405h]char v4[256]; // [esp4h] [ebp-404h] BYREFchar Format[256]; // [esp104h] [ebp-304h] BYREFchar v6[256]; // [esp204h] [ebp-204h] BYREFchar v7[256]; // [esp304h] [ebp-10…...
Python中的单例模式:深入探索元类与装饰器实现
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 单例模式(Singleton Pattern)是设计模式中的一种重要模式,确保一个类在整个应用中只有一个实例,并且提供全局访问点。Python语言作为一…...
深入解析 Babylon.js 中的 TransformNode.lookAt 方法
在 3D 开发中,控制对象朝向是一个基础但关键的需求。Babylon.js 作为一款强大的 Web3D 引擎,提供了 TransformNode.lookAt 方法来实现这一功能。本文将全面解析这个方法的使用技巧、参数含义以及常见应用场景。 方法基础 TransformNode.lookAt 的基本签…...
SpringCloud组件——Gateway
一.网关 1.问题提出 我们通过Eureka,Nacos解决了服务注册,服务发现的问题,使用SpringCloud LoadBalance解决了负载均衡的问题,使用OpenFeign解决了远程调用的问题。 但是当前所有微服务的接口都是直接对外暴露的,可…...
Boost 库安装 (windows 11)
Boost 库安装 (windows 11 1 下载2 生成3 使用 1 下载 下载地址:https://www.boost.org/ 有的时候会需要历史版本下载: https://www.boost.org/users/history/ 2 生成 1、解压后点击 bootstrap.bat,会生成可执行程序b2.exe 2、双击运行b2.…...
lmms-eval--微调实战笔记
lmms-eval--大模型调用平台,方便新手上手大模型微调 lmms-eval的更多用法,没有mathversehttps://github.com/EleutherAI/lm-evaluation-harness.git 单卡运行,模型gpt-j-6B,数据集hellaswag git clone --depth 1 https://github.com/Eleuthe…...
序列密码算法ShanLooog512设计原理详解
序列密码算法ShanLooog512设计原理详解 ShanLooog512(闪龙512)为序列密码算法,内部状态为512比特,密钥长度为128或256比特,轮函数为FFFFFFFF,循环轮数为24轮,输出密钥流为512比特的状态。与Salsa20类似,内…...
Matplotlib可视化基础
1. 折线图 matplotlib.pyplot.plot() # 主要参数: x,y -- 接收array,表示X轴和Y轴对应的数据,无默认 color -- 接收特定string,指定线条的颜色,默认为None linestyle -- 接收特定string,指定线条的类型…...
Linux 内核网络协议栈中的关键数据结构:inet_skb_parm 与 ip_options
在 Linux 内核的网络协议栈中,数据包的高效处理依赖于一系列精心设计的数据结构。这些结构体不仅需要存储网络数据的元信息,还需支持复杂的协议逻辑(如路由、分片、安全策略等)。本文聚焦两个核心结构体 struct inet_skb_parm 和 struct ip_options,解析它们的设计原理、功…...
oracle 数据库查询指定用户下每个表占用空间的大小,倒序显示
oracle 查询指定用户下每个表占用空间的大小,倒序显示 使用场景:数据分析;导出医院正式库到开发环境时,查询出占用表空间高的业务表、导出时排除该表 在Oracle数据库中,要查询指定用户下每个表占用空间的大小并以倒序…...
Missashe考研日记-day29
Missashe考研日记-day29 1 专业课408 学习时间:3h学习内容: 今天先是把虚拟存储剩余的课听完了,然后就是做课后选择题,57道,已经接受了OS课后题尤其多的事实了。解决并且理解完习题之后就开始预习文件管理的内容&…...
【AI】【MCP】搭建私人王炸MCP自动化工作流
目录 一、什么是MCP 二、MCP大集合 三、准备工作 3.1 安装node.js 3.2 安装vscode 3.3 安装cline插件 3.3.1 安装 3.3.2 配置Cline 四、配置MCP服务 4.1 Search-mcp服务 4.2 playwright-mcp 服务 前言:梦想组合,轻松办公,告别手动&a…...
多元函数微分之传统方法和全微分法
一、传统方法 使用链式法则,先对中间变量(如 u,v)求偏导,再乘以中间变量对最终变量(如 x,y)的偏导。 二、全微分法 基于全微分形式不变性,直接对 zf(u,v) 求全微分 dz,再代入 du 和…...
新手SEO基础优化全解析
内容概要 对于刚接触SEO的新手而言,系统化理解优化逻辑是避免无效操作的关键。本文将从基础概念入手,逐步拆解搜索引擎排名的影响要素,围绕关键词分析、技术优化、内容策略三大核心模块,提供可落地的操作框架。通过结合工具使用说…...
MATLAB退火算法和遗传算法解决旅行商问题
模拟退火算法和遗传算法都是常用于解决旅行商问题(TSP)的优化算法,它们在原理、搜索方式、收敛速度和适用场景等方面存在一些区别: 原理 模拟退火算法:模拟退火算法的灵感来源于固体退火原理。固体在加热后缓慢冷却时…...
喜马拉雅卖身腾讯音乐:在线音频独立时代的终结
坦白说,这条消息一出来,喜马拉雅被卖掉不太奇怪,但是腾讯音乐会收购,还是有点意外。 喜马拉雅之前一度被称为中国版Audible平台,在过去几年里,活生生地把一手好牌打得稀烂。如今走到“卖身”这一步,既是无奈,也是必然。 简单回顾一下背景: 2012年,喜马拉雅成立,一…...
简单理解https与http
都是超文本传输协议,一个安全一个不安全,名字长的安全,名字短的不安全。 安全与不安全是居于什么分别的? 通过加密 http无加密。 httpshttp SSL/TSL(加密)来保障数据安全。加密传输 身份验证 SSL/TLS…...
打造即插即用的企业级云原生平台——KubeSphere 4.1 扩展组件在生产环境的价值全解
目录 打造即插即用的企业级云原生平台——KubeSphere 4.1 扩展组件在生产环境的价值全解 1. 可观测体系:WhizardTelemetry 全家桶 2. 平台与多集群治理 3. CI/CD 与交付效率 4. 网络与流量入口 5. 安全与合规 6. 存储与数据保护 7. 平台集成优势 结语 打造…...
配置扩展ACL
1.扩展ACL简介: 扩展ACL可以更精确地控制基于源IP地址、目标IP地址、协议类型和端口号的流量。 2.配置背景: 为了实现公司内部只能使用FTP服务器传输文件并关闭其他所有服务和端口的需求,可以通过配置访问控制列表(ACL…...
根据用户出生日期计算年龄
public static int calculateAgeFromDate(Date birthDate) { // 将 Date 转换为 LocalDate(默认时区) LocalDate birthLocalDate birthDate.toInstant() .atZone(ZoneId.systemDefault()) .toLocalDate(); // 获取当前日期LocalDate currentDate Local…...
测试基础笔记第十五天
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、集合1.集合的定义二、使用集合列表去重 导包二、函数1.函数介绍2.定义函数3.调用函数4.函数实现登录案例5.函数的返回值 三、模块和包1.模块的概念(Module)2.模…...
【专题四】前缀和(3)
📝前言说明: 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录,按专题划分每题主要记录:(1)本人解法 本人屎山代码;(2)优质解法 优质代码;ÿ…...
STM32 USB配置详解
STM32 USB配置详解 一、USB基础概念 1.1 USB简介 USB (Universal Serial Bus) 是一种用于计算机与外部设备连接的串行总线标准,具有热插拔、即插即用等特点。STM32微控制器内置了多种USB接口,可实现各类USB应用。 1.2 USB速度等级 Low Speed (LS): …...
2025年Mapbox零基础入门教程(1)地图初始化
什么是mapbox? mapbox是一个地图框架,不仅提供前端渲染能力,还具备后端服务接口能力。 相较于openlayers,它可构建二维和三维地图,并支持优化导航路线和位置查询等功能。 开发中使用mapbox需引入库文件并设置token&…...
课外知识:你需要了解的Python类对象里面的__getattr__方法
你需要了解的Python类对象中的__getattr__方法 一、__getattr__基础概念 1. 方法定义 def __getattr__(self, name: str) -> Any:"""当访问不存在的属性时触发"""2. 核心特性 动态属性处理:拦截未定义的属性访问按需触发&…...
openGauss新特性 | DataKit支持PostgreSQL到openGauss的迁移能力
Postgresql-\>openGauss迁移工具debezium-connector-postgres 可获得性 本特性自openGauss 7.0.0-RC1版本开始引入。 特性简介 debezium-connector-postgres工具是一个基于Java语言的Postgresql到openGauss的复制工具。该工具提供了初始全量数据及对象(视图、…...
【前端】跟进新趋势- PWA WebAssembly
不定期更新及补充实战。建议关注收藏点赞。 目录 PWA(渐进式 Web 应用,Progressive Web App)WebAssembly(WASM) PWA(渐进式 Web 应用,Progressive Web App) PWA 是一种提升 Web 应用…...
C++学习:六个月从基础到就业——模板编程:SFINAE原则
C学习:六个月从基础到就业——模板编程:SFINAE原则 本文是我C学习之旅系列的第三十六篇技术文章,也是第二阶段"C进阶特性"的第十四篇,主要介绍C模板编程中的SFINAE原则。查看完整系列目录了解更多内容。 目录 C学习之…...
完美解决.NET Framework 4.0 中 System.Drawing 库不支持 WebP 格式的图像处理
如果你想在 .NET Framework 4.0 中使用 ImageMagick 处理图片,可以通过 Magick.NET 库来实现。Magick.NET 是 ImageMagick 的 .NET 封装,可以用来读取、写入、编辑图像。 以下是如何使用 Magick.NET 来处理图像并提取图像的宽度和高度。 步骤ÿ…...
网络基础概念:从菜鸟到入门
前言:快递小哥的故事 想象一下你要给朋友寄个礼物,这个过程其实和网络通信非常相似: 1. 你需要知道朋友的”地址“(IP地址) 2. 要注明是送到他家大门还是物业代收(端口号) 3. 要选择快递公司并…...
优先队列和单调队列(双端队列实现的)
这里写自定义目录标题 一、优先队列与单调队列二、优先队列2.1 概念2.2 增删查 判空2.3 示例代码 三、双端队列四、单调队列4.1 单调递增队列4.2 单调递减队列 一、优先队列与单调队列 二、优先队列 2.1 概念 一种特殊的队列,它与普通队列的主要区别在于元素的出…...
设计模式(状态模式)
概述 在实际的软件开发中,状态模式并不是很常用,但是在能够用到的场景里,它可以发挥很大的作用。从这一点上来看,它有点像我们之前讲到的组合模式。 状态模式一般用来实现状态机,而状态机常用在游戏、工作流引擎等系统…...
安卓基础(get和set)
在 Java 中,get 和 set 方法是面向对象编程中 封装(Encapsulation) 的核心实现,用于安全地访问和修改类的私有字段(private 成员变量)。它们的核心作用是 控制对数据的访问,…...
机器人灵巧操作新突破,力感知技术让机械手更精准
在机器人的发展历程中,让机器人实现灵活操作一直是科研人员努力攻克的难题。 我们这篇文章给大家带来一份新的工作:DexForce 链接:[2501.10356] DexForce: Extracting Force-informed Actions from Kinesthetic Demonstrations for Dextero…...
八大排序——直接插入排序/希尔排序
八大排序——直接插入排序/希尔排序 目录 一、直接插入排序 二、希尔排序 一、直接插入排序 每一趟从待排序序列中取第一个值,将其插入到已排序好的序列中,对已排序好的序列,从右到左依次和待插入值比较,如果大于则向后挪&…...
8、HTTPD服务--ab压力测试
一、ab压力测试 # ab ‐c 100 ‐n 1000 http://vedio.linux.com/index.html 2 This is ApacheBench, Version 2.3 <$Revision: 1430300 $> 3 Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 4 Licensed to The Apache Software Foundation,…...
node.js 实战——mongoDB
MongoDB MongoDB 简介 MongoDB 是一种基于文档型 (document-oriented) 的 NoSQL 数据库,使用类 JSON 的 BSON 格式存储数据,自然支持复杂数据结构。它特别适合需要快速变化、大量数据处理和高应用扩展性的场景。 MongoDB 特性: 无法表、无…...
C语言学习路线
以下是一份综合多个优质资源的C语言学习路线规划,结合2025年最新技术趋势和工程实践需求,分为三个阶段系统推进: 一、入门阶段(1-2个月) 目标:掌握基础语法,能编写简单程序ÿ…...
飞凌嵌入式T527核心板获得【OpenHarmony生态产品兼容性证书】
近日,飞凌嵌入式FET527-C核心板通过OpenHarmony 4.1 Release版本兼容测评,获得【OpenHarmony生态产品兼容性证书】。 飞凌嵌入式FET527-C核心板搭载全志T527系列全国产高性能处理器,集成8个ARM Cortex-A55核心,并内置RISC-V核和DS…...