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

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)为避免命名冲突&#xff0c;需要创建一个命名空间来存放模拟实现的 list (2)下面模拟实现list时&#xff0c;声明和定义不分离(具体原因后续讲解) 2.完整实现 2.1 链表节点 template<class T>//节点写成类模板…...

数字图像处理 -- 眼底图像血管分割方法

算法框架 基于深度学习的 U-Net 架构&#xff0c;结合注意力机制&#xff08;Attention Gate&#xff09;与多尺度特征提取&#xff0c;以提高细小血管的检测能力。整体流程如下&#xff1a; 输入图像预处理&#xff1a;提取绿色通道 & CLAHE 增强数据增强&#xff1a;旋…...

基于ffmpeg的音视频编码

1 音频编码 本质上是由pcm文件转到一个协议文件 比如说aac协议 1.1 音频基本知识回归 比特率 比特率是指单位时间内传输或处理的比特&#xff08;bit&#xff09;数量&#xff0c;通常用 bps&#xff08;bits per second&#xff0c;比特每秒&#xff09;来表示。它是衡量数…...

Android wifi开发调试总结

Android wifi开发调试简单总结 文章目录 Android wifi开发调试简单总结一、前言二、wifi demo开发1、开关和连接2、wifi开启主要流程3 、wifi主要广播4、相关日志5、demo示例 三、其他1、Wifi开发小结2、其他wifi知识小结&#xff08;1&#xff09;Android无线Wifi开发&#xf…...

LLVIP、KAIST、M3FD数据集

LLVIP、KAIST、M3FD数据集 &#xff08;可见光红外&#xff0c;双模态数据集&#xff0c;已配准已对齐已清洗&#xff0c;已处理为txt格式&#xff0c;YOLO可直接训练&#xff09; 电子产品&#xff0c;一经出售&#xff0c;概不退换 算法设计、毕业设计、期刊专利&#xff01;…...

datasets 数据处理封装后,统一处理流程以避免Dataset Map顺序依赖问题

文章目录 处理流程说明小结 在实际项目中&#xff0c;我们常常需要对数据集进行预处理。为了规范操作&#xff0c;我封装了一个基础数据集处理类&#xff1a; class DatasetAbstract:"""所有数据集都应包含以下几个字段&#xff1a;* question&#xff1a;用户…...

【学习笔记】机器学习(Machine Learning) | 第四章(3)| 多变量线性回归

机器学习&#xff08;Machine Learning&#xff09; 简要声明 基于吴恩达教授(Andrew Ng)课程视频 BiliBili课程资源 文章目录 机器学习&#xff08;Machine Learning&#xff09;简要声明 三、特征工程与多项式回归&#xff08;一&#xff09;特征工程&#xff1a;从数据中发…...

将本地Springboot项目部署到Linux服务器

1、打包后端项目 在IDEA的终端上执行命令 mvn clean package "-Dmaven.test.skiptrue" 在target目录下查看jar包是否存在 2、idea运行jar包&#xff08;可选&#xff09; 在IDEA的终端上执行命令 # 进入jar包所在目录 E:\LzpWorkspaces\lzp-records> cd .\tar…...

无人设备遥控器之实时数据保护技术篇

无人设备遥控器的实时数据保护技术是保障设备安全运行、避免信息泄露或恶意干扰的核心手段&#xff0c;其核心目标是在复杂电磁环境和网络攻击威胁下&#xff0c;确保指令传输的完整性、保密性和抗干扰性。 一、技术实现路径 链路层加密与认证 动态密钥协商&#xff1a;采用…...

【优秀三方库研读】【性能优化点滴】odygrd/quill 解决伪共享

一、伪共享&#xff08;False Sharing&#xff09;问题本质 当不同CPU核心频繁修改**同一缓存行&#xff08;Cache Line&#xff09;**中的不同变量时&#xff0c;会导致严重的性能下降。现代CPU的缓存系统以缓存行&#xff08;通常64字节&#xff09;为单位操作内存&#xff…...

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 开发中&#xff0c;控制对象朝向是一个基础但关键的需求。Babylon.js 作为一款强大的 Web3D 引擎&#xff0c;提供了 TransformNode.lookAt 方法来实现这一功能。本文将全面解析这个方法的使用技巧、参数含义以及常见应用场景。 方法基础 TransformNode.lookAt 的基本签…...

SpringCloud组件——Gateway

一.网关 1.问题提出 我们通过Eureka&#xff0c;Nacos解决了服务注册&#xff0c;服务发现的问题&#xff0c;使用SpringCloud LoadBalance解决了负载均衡的问题&#xff0c;使用OpenFeign解决了远程调用的问题。 但是当前所有微服务的接口都是直接对外暴露的&#xff0c;可…...

Boost 库安装 (windows 11)

Boost 库安装 (windows 11 1 下载2 生成3 使用 1 下载 下载地址&#xff1a;https://www.boost.org/ 有的时候会需要历史版本下载&#xff1a; https://www.boost.org/users/history/ 2 生成 1、解压后点击 bootstrap.bat&#xff0c;会生成可执行程序b2.exe 2、双击运行b2.…...

lmms-eval--微调实战笔记

lmms-eval--大模型调用平台&#xff0c;方便新手上手大模型微调 lmms-eval的更多用法,没有mathversehttps://github.com/EleutherAI/lm-evaluation-harness.git 单卡运行&#xff0c;模型gpt-j-6B&#xff0c;数据集hellaswag git clone --depth 1 https://github.com/Eleuthe…...

序列密码算法ShanLooog512设计原理详解

序列密码算法ShanLooog512设计原理详解 ShanLooog512(闪龙512)为序列密码算法&#xff0c;内部状态为512比特&#xff0c;密钥长度为128或256比特&#xff0c;轮函数为FFFFFFFF&#xff0c;循环轮数为24轮&#xff0c;输出密钥流为512比特的状态。与Salsa20类似&#xff0c;内…...

Matplotlib可视化基础

1. 折线图 matplotlib.pyplot.plot() # 主要参数&#xff1a; x,y -- 接收array&#xff0c;表示X轴和Y轴对应的数据&#xff0c;无默认 color -- 接收特定string&#xff0c;指定线条的颜色&#xff0c;默认为None linestyle -- 接收特定string&#xff0c;指定线条的类型…...

Linux 内核网络协议栈中的关键数据结构:inet_skb_parm 与 ip_options

在 Linux 内核的网络协议栈中,数据包的高效处理依赖于一系列精心设计的数据结构。这些结构体不仅需要存储网络数据的元信息,还需支持复杂的协议逻辑(如路由、分片、安全策略等)。本文聚焦两个核心结构体 struct inet_skb_parm 和 struct ip_options,解析它们的设计原理、功…...

oracle 数据库查询指定用户下每个表占用空间的大小,倒序显示

oracle 查询指定用户下每个表占用空间的大小&#xff0c;倒序显示 使用场景&#xff1a;数据分析&#xff1b;导出医院正式库到开发环境时&#xff0c;查询出占用表空间高的业务表、导出时排除该表 在Oracle数据库中&#xff0c;要查询指定用户下每个表占用空间的大小并以倒序…...

Missashe考研日记-day29

Missashe考研日记-day29 1 专业课408 学习时间&#xff1a;3h学习内容&#xff1a; 今天先是把虚拟存储剩余的课听完了&#xff0c;然后就是做课后选择题&#xff0c;57道&#xff0c;已经接受了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 服务 前言&#xff1a;梦想组合&#xff0c;轻松办公&#xff0c;告别手动&a…...

多元函数微分之传统方法和全微分法

一、传统方法 使用链式法则&#xff0c;先对中间变量&#xff08;如 u,v&#xff09;求偏导&#xff0c;再乘以中间变量对最终变量&#xff08;如 x,y&#xff09;的偏导。 二、全微分法 基于全微分形式不变性&#xff0c;直接对 zf(u,v) 求全微分 dz&#xff0c;再代入 du 和…...

新手SEO基础优化全解析

内容概要 对于刚接触SEO的新手而言&#xff0c;系统化理解优化逻辑是避免无效操作的关键。本文将从基础概念入手&#xff0c;逐步拆解搜索引擎排名的影响要素&#xff0c;围绕关键词分析、技术优化、内容策略三大核心模块&#xff0c;提供可落地的操作框架。通过结合工具使用说…...

MATLAB退火算法和遗传算法解决旅行商问题

模拟退火算法和遗传算法都是常用于解决旅行商问题&#xff08;TSP&#xff09;的优化算法&#xff0c;它们在原理、搜索方式、收敛速度和适用场景等方面存在一些区别&#xff1a; 原理 模拟退火算法&#xff1a;模拟退火算法的灵感来源于固体退火原理。固体在加热后缓慢冷却时…...

喜马拉雅卖身腾讯音乐:在线音频独立时代的终结

坦白说,这条消息一出来,喜马拉雅被卖掉不太奇怪,但是腾讯音乐会收购,还是有点意外。 喜马拉雅之前一度被称为中国版Audible平台,在过去几年里,活生生地把一手好牌打得稀烂。如今走到“卖身”这一步,既是无奈,也是必然。 简单回顾一下背景: 2012年,喜马拉雅成立,一…...

简单理解https与http

都是超文本传输协议&#xff0c;一个安全一个不安全&#xff0c;名字长的安全&#xff0c;名字短的不安全。 安全与不安全是居于什么分别的&#xff1f; 通过加密 http无加密。 httpshttp SSL/TSL&#xff08;加密&#xff09;来保障数据安全。加密传输 身份验证 SSL/TLS…...

打造即插即用的企业级云原生平台——KubeSphere 4.1 扩展组件在生产环境的价值全解

目录 打造即插即用的企业级云原生平台——KubeSphere 4.1 扩展组件在生产环境的价值全解 1. 可观测体系&#xff1a;WhizardTelemetry 全家桶 2. 平台与多集群治理 3. CI/CD 与交付效率 4. 网络与流量入口 5. 安全与合规 6. 存储与数据保护 7. 平台集成优势 结语 打造…...

配置扩展ACL

1.扩展ACL简介&#xff1a; 扩展ACL可以更精确地控制基于源IP地址、目标IP地址、协议类型和端口号的流量。 2.配置背景&#xff1a; 为了实现公司内部只能使用FTP服务器传输文件并关闭其他所有服务和端口的需求&#xff0c;可以通过配置访问控制列表&#xff08;ACL&#xf…...

根据用户出生日期计算年龄

public static int calculateAgeFromDate(Date birthDate) { // 将 Date 转换为 LocalDate&#xff08;默认时区&#xff09; LocalDate birthLocalDate birthDate.toInstant() .atZone(ZoneId.systemDefault()) .toLocalDate(); // 获取当前日期LocalDate currentDate Local…...

测试基础笔记第十五天

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、集合1.集合的定义二、使用集合列表去重 导包二、函数1.函数介绍2.定义函数3.调用函数4.函数实现登录案例5.函数的返回值 三、模块和包1.模块的概念(Module)2.模…...

【专题四】前缀和(3)

&#x1f4dd;前言说明&#xff1a; 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录&#xff0c;按专题划分每题主要记录&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代码&#xff1b;&#xff08;2&#xff09;优质解法 优质代码&#xff1b;&#xff…...

STM32 USB配置详解

STM32 USB配置详解 一、USB基础概念 1.1 USB简介 USB (Universal Serial Bus) 是一种用于计算机与外部设备连接的串行总线标准&#xff0c;具有热插拔、即插即用等特点。STM32微控制器内置了多种USB接口&#xff0c;可实现各类USB应用。 1.2 USB速度等级 Low Speed (LS): …...

2025年Mapbox零基础入门教程(1)地图初始化

什么是mapbox&#xff1f; mapbox是一个地图框架&#xff0c;不仅提供前端渲染能力&#xff0c;还具备后端服务接口能力。 相较于openlayers&#xff0c;它可构建二维和三维地图&#xff0c;并支持优化导航路线和位置查询等功能。 开发中使用mapbox需引入库文件并设置token&…...

课外知识:你需要了解的Python类对象里面的__getattr__方法

你需要了解的Python类对象中的__getattr__方法 一、__getattr__基础概念 1. 方法定义 def __getattr__(self, name: str) -> Any:"""当访问不存在的属性时触发"""2. 核心特性 动态属性处理&#xff1a;拦截未定义的属性访问按需触发&…...

openGauss新特性 | DataKit支持PostgreSQL到openGauss的迁移能力

Postgresql-\>openGauss迁移工具debezium-connector-postgres 可获得性 本特性自openGauss 7.0.0-RC1版本开始引入。 特性简介 debezium-connector-postgres工具是一个基于Java语言的Postgresql到openGauss的复制工具。该工具提供了初始全量数据及对象&#xff08;视图、…...

【前端】跟进新趋势- PWA WebAssembly

不定期更新及补充实战。建议关注收藏点赞。 目录 PWA&#xff08;渐进式 Web 应用&#xff0c;Progressive Web App&#xff09;WebAssembly&#xff08;WASM&#xff09; PWA&#xff08;渐进式 Web 应用&#xff0c;Progressive Web App&#xff09; PWA 是一种提升 Web 应用…...

C++学习:六个月从基础到就业——模板编程:SFINAE原则

C学习&#xff1a;六个月从基础到就业——模板编程&#xff1a;SFINAE原则 本文是我C学习之旅系列的第三十六篇技术文章&#xff0c;也是第二阶段"C进阶特性"的第十四篇&#xff0c;主要介绍C模板编程中的SFINAE原则。查看完整系列目录了解更多内容。 目录 C学习之…...

完美解决.NET Framework 4.0 中 System.Drawing 库不支持 WebP 格式的图像处理

如果你想在 .NET Framework 4.0 中使用 ImageMagick 处理图片&#xff0c;可以通过 Magick.NET 库来实现。Magick.NET 是 ImageMagick 的 .NET 封装&#xff0c;可以用来读取、写入、编辑图像。 以下是如何使用 Magick.NET 来处理图像并提取图像的宽度和高度。 步骤&#xff…...

网络基础概念:从菜鸟到入门

前言&#xff1a;快递小哥的故事 想象一下你要给朋友寄个礼物&#xff0c;这个过程其实和网络通信非常相似&#xff1a; 1. 你需要知道朋友的”地址“&#xff08;IP地址&#xff09; 2. 要注明是送到他家大门还是物业代收&#xff08;端口号&#xff09; 3. 要选择快递公司并…...

优先队列和单调队列(双端队列实现的)

这里写自定义目录标题 一、优先队列与单调队列二、优先队列2.1 概念2.2 增删查 判空2.3 示例代码 三、双端队列四、单调队列4.1 单调递增队列4.2 单调递减队列 一、优先队列与单调队列 二、优先队列 2.1 概念 一种特殊的队列&#xff0c;它与普通队列的主要区别在于元素的出…...

设计模式(状态模式)

概述 在实际的软件开发中&#xff0c;状态模式并不是很常用&#xff0c;但是在能够用到的场景里&#xff0c;它可以发挥很大的作用。从这一点上来看&#xff0c;它有点像我们之前讲到的组合模式。 状态模式一般用来实现状态机&#xff0c;而状态机常用在游戏、工作流引擎等系统…...

安卓基础(get和set)

在 Java 中&#xff0c;​​get 和 set​​ 方法是面向对象编程中 ​​封装&#xff08;Encapsulation&#xff09;​​ 的核心实现&#xff0c;用于安全地访问和修改类的私有字段&#xff08;private 成员变量&#xff09;。它们的核心作用是 ​​控制对数据的访问&#xff0c…...

机器人灵巧操作新突破,力感知技术让机械手更精准

在机器人的发展历程中&#xff0c;让机器人实现灵活操作一直是科研人员努力攻克的难题。 我们这篇文章给大家带来一份新的工作&#xff1a;DexForce 链接&#xff1a;[2501.10356] DexForce: Extracting Force-informed Actions from Kinesthetic Demonstrations for Dextero…...

八大排序——直接插入排序/希尔排序

八大排序——直接插入排序/希尔排序 目录 一、直接插入排序 二、希尔排序 一、直接插入排序 每一趟从待排序序列中取第一个值&#xff0c;将其插入到已排序好的序列中&#xff0c;对已排序好的序列&#xff0c;从右到左依次和待插入值比较&#xff0c;如果大于则向后挪&…...

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 数据库&#xff0c;使用类 JSON 的 BSON 格式存储数据&#xff0c;自然支持复杂数据结构。它特别适合需要快速变化、大量数据处理和高应用扩展性的场景。 MongoDB 特性&#xff1a; 无法表、无…...

C语言学习路线

以下是一份综合多个优质资源的C语言学习路线规划&#xff0c;结合2025年最新技术趋势和工程实践需求&#xff0c;分为三个阶段系统推进&#xff1a; ​一、入门阶段&#xff08;1-2个月&#xff09;​​ ​目标​&#xff1a;掌握基础语法&#xff0c;能编写简单程序&#xff…...

飞凌嵌入式T527核心板获得【OpenHarmony生态产品兼容性证书】

近日&#xff0c;飞凌嵌入式FET527-C核心板通过OpenHarmony 4.1 Release版本兼容测评&#xff0c;获得【OpenHarmony生态产品兼容性证书】。 飞凌嵌入式FET527-C核心板搭载全志T527系列全国产高性能处理器&#xff0c;集成8个ARM Cortex-A55核心&#xff0c;并内置RISC-V核和DS…...