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

list的使用以及模拟实现

本章目标

1.list的使用
2.list的模拟实现

1.list的使用

在这里插入图片描述
在stl中list是一个链表,并且是一个双向带头循环链表,这种结构的链表是最优结构.
因为它的实现上也是一块线性空间,它的使用上是与string和vector类似的.但相对的因为底层物理结构上它并不像vector是线性连续的,它并没有重载像[]这样的运算符,也没有重载流插入流提取这样的操作.
在这里的使用我们只介绍它的最为特别的接口

1.1sort

在这里插入图片描述

在这里list专门提供了一个sort接口用来排序,因为list的迭代器原因它并不能使用算法库中的sort,并且两个sort的底层并不相同.
在这里插入图片描述
在算法库中要求的sort是一个随机迭代器.而对于list来说,因为它底层的实现原因,它的底层是一个双向迭代器.
在这里插入图片描述
在c++中一共有三种迭代器.
随机迭代器,双向迭代器,单向迭代器
在这里插入图片描述
对于这三种迭代器它们支持的操作是从右到左依此兼容的.
在这里插入图片描述
例如要求双向迭代器的reverse接口是可以传随机迭代器的
在这里插入图片描述
对于这两个sort来说,算法库中的sort的底层是快排,而在list容器中的sort底层是用的是归并排序.
因为双向迭代器是不支持相减操作的,而在快排中有一个找基准值的过程,我们会用左右端点相减来去取基准值防止排序的时间复杂度达到n方的程度.
并且这个list中的sort的效率并不如算法库中的sort效率高

1.2remove和remove_if

而者整体的逻辑都是删除特定值,但是remove是移除给你传过去val相等的值,remove_If是删除满足特定条件的值
在这里插入图片描述

在这里插入图片描述

1.3splice和merge

在这里插入图片描述
在这里插入图片描述
我们先说第一个接口,这个接口的作用是两个list相互拼接起来.
在这里插入图片描述
在这里插入图片描述
我们可以拼接整个链表也可拼接某个迭代器位置的,也可以拼接某个迭代器区间.
但是我们用来拼接的那个链表被拼接的地方将会消失
在这里插入图片描述
我们再来说第二个接口,它的作用是用来合并两个有序list到一个list中,
在这里我们提供一段代码供大家测试

#include <iostream>
#include <list>// compare only integral part:
bool mycomparison (double first, double second)
{ return ( int(first)<int(second) ); }int main ()
{std::list<double> first, second;first.push_back (3.1);first.push_back (2.2);first.push_back (2.9);second.push_back (3.7);second.push_back (7.1);second.push_back (1.4);first.sort();second.sort();first.merge(second);// (second is now empty)second.push_back (2.1);first.merge(second,mycomparison);std::cout << "first contains:";for (std::list<double>::iterator it=first.begin(); it!=first.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;

1.4unique

在这里插入图片描述

这个接口的作用是用来去除当前list中相同的元素,但是去除相同的元素是有要求的,它是要求我们的list是有序的.

2.list的模拟实现

因为list的底层并不是一块连续的物理空间,在不同的stl版本中实现并不相同,c++标准并没有规定他是怎么实现的,我们只需要将其进行封装,给予接口供其使用即可.
我们在这里实现list的结构是参考gcc的SGI版本的stl.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在SGI版本的stl中,将链表结点,迭代器,链表封装为三个类.
并且链表结点和迭代器的实现,并没有class而是用的struct,将所有成员都开放为公有.
因为我们在使用list的时候,并不会去通过链表结点和迭代器去进行内部的访问,而且因为c++标准并没有明确规定.各个平台环境下实现也各有不同.如果使用就会出现移植性问题.者也算是一种隐形的封装.

2.0list容器的构成

跟据SGI版本的源码,我们也实现三个类,list,list_node,list_iterator

template <class T>
struct List_Node
{List_Node* prev;List_Node* next;T data;List_Node(const T& val = T()):prev(nullptr), next(nullptr), data(val){}
};
template <class T >
struct list_iterator
{typedef List_Node<T> Node;typedef list_iterator<T> self;Node* node;list_iterator( Node* val):node(val){}
}:
template <class T>
class list
{typedef List_Node<T> Node;public:list()
{head = new Node;head->next = head;head->prev = head;
}
private:Node* head;size_t _size;};

1.在这里面我们将所有需要用到模板的地方都进行了typedef,者样做第一个是为了封装,我们在这里面使用list只给客户提供接口,并不希望,它们,通过通过结点和迭代器进行访问.第二是为了我们实现的方便.
2.对于迭代器,我们主要实现它解引用.我们要通过这个迭代器去访问它的数据.
所以它的底层也因该是一个结点类型的指针,
3.对于结点的构造函数.我们在给val缺省值的时候,给了一个匿名对象,这样如果我们要给的值是一个自定义类型,它就会调用它的构造,如果是内置类型也是调用一个默认构造.

2.1插入删除

因为list底层的结构是一个双向带头循环的链表.它的逻辑上的结构是和我之前发的博客是一致的.
我们在这里涉及底层逻辑,不过多阐述.只提与之有出入的地方.

void push_back(const T& x)
{/*Node* tail = head->prev;Node* newnode = new Node(x);tail->next = newnode;newnode->prev = tail;newnode->next = head;head->prev = newnode;*/insert(end(), x);
}

在这里我们可以主动实现(注释中的代码)也可以复用后面要实现的insert函数.

2.1.1insert
void insert(iterator pos, const T& val)
{//prev newnode  cur Node* prev = pos.node->prev;Node* cur = pos.node;Node* newnode = new Node(val);prev->next = newnode;cur->prev = newnode;newnode->prev = prev;newnode->next = cur;++_size;
}

逻辑上和之前的双向链表是一样的但是与之前不同的是,在这里我们传的是一个迭代器.

2.1.2erase
iterator erase(iterator pos)
{//prev pos nextNode* prev = pos.node->prev;Node* next = pos.node->next;Node* cur = pos.node;prev->next = next;next->prev = prev;delete cur;--_size;//return next;return iterator(next);
}

对于erase来说,要注意迭代器失效的问题.要返回被删位置的迭代器.
在这里我们也给一个用next结点指针初始化的匿名对象.

void push_front(const T& x)
{insert(begin(), x);
}
void pop_front()
{erase(begin());
}
void pop_back()
{erase(--end());
}

对于它们的尾插头插的复用,我们需要实现list中begin(),end(),迭代器++,–等接口.

iterator begin()
{return iterator(head->next);
}
iterator end()
{return iterator(head);
}

因为begin和end是一对左闭右开的区间.我们又是一个双向链表.
它存储数据的第一个位置begin是头节点的下一个结点.
它的end是最后存储数据的下一个结点.也就是哨兵位.

Ref operator*()
{return node->data;
}
self& operator++()
{node = node->next;return *this;
}
self operator++(int)
{self tmp(*this);node = node->next;return tmp;
}
self& operator--()
{node = node->prev;return *this;
}
self operator--(int)
{self tmp(*this);node = node->prev;return tmp;
}
bool operator!=(const self& it)
{return node != it.node;
}
bool operator==(const self& it)
{return node == it.node;
}

我的迭代器主要是为了遍历修改.而list是需要迭代器是实现这些运算符重载去完成上面的功能的.对于这些运算符重载是和我们之前学过的日期类的整体逻辑是相似的.在这里不做过多赘述.

2.2const迭代器

对于const迭代器来说,我们至于要要让迭代器指向的对象值不被修改即可.我们至于要修改*的运算符重载.,让它返回的对象是一个const对象即可.但是再重新写一个类的开销太大了.我们可以多给一个模板参数.

template <class T ,class Ref,class Ptr>
struct list_iterator
{typedef List_Node<T> Node;typedef list_iterator<T,Ref,Ptr> self;

用ref代替*运算符重载的返回值

Ref operator*()
{return node->data;
}

我们至于要再list里面传两个不同的模板类的参数即可.
本质上还是写了两个类.只不过有了模板,我们实际上是让编译器干了这个活.

	typedef list_iterator<T, T&,T*> iterator;typedef list_iterator<T,const T&,const T*>  const_iterator;
	const_iterator begin() const{return const_iterator(head->next);}const_iterator end() const{return const_iterator(head);}

再list这个类中,我们再给两个begin,和end的函数重载.
不过它们的返回值就要给const_iterator这个类的匿名对象.

3.其他构造函数,拷贝,赋值运算符重载,析构

它也支持initializer_list的构造.迭代器区间构造.但是它们都面临一个问题,它们要初始化头结点.我们只需要将默认构造那一部分进行封装.

void empty()
{head = new Node;head->next = head;head->prev = head;_size = 0;
}

因为list需要进行深拷贝.我们可以先实现list的swap,然后实现拷贝,赋值运算符重载.都可以用现代写法.

void swap(const list<T>& it)
{std::swap(head, it.head);std::swap(size, it.size);
}
list(const list<T>& it)
{empty();for (auto& ch : it){push_back(ch);}
}
list<T>& operator=(list<T> val){swap(val);return *this;}

对于它的析构函数,我们先要实现它的clear函数.clear,函数是清除头结点以外的结点.析构实在clear的基础上再对头节点进行释放.

void clear()
{iterator cur = begin();while (cur != end()){cur = erase(cur);}
}
~list()
{clear();delete head;head = nullptr;cout << "~list" << endl;
}

4.对于自定义类型的->运算符重载

struct C
{int a ;int b;C(int a = 2,int b = 1):a(a),b(b){}
};

假设我们有这么一个类.我们对这个类

	list<C> c;c.push_back({ 1,2 });c.push_back({ 4,3 });c.push_back({ 5,2 });auto it = c.begin();while (it != c.end()){//cout << it->a << it->b << " ";cout << it.operator->()->a << it.operator->()->b << " ";it++;}cout << endl;

我们要访问struct的成员变量的时候,如果这个类没有实现它的流插入流提取运算符重载.我们需要主动取访问它的内部的变量去间接访问.我们可以提前再迭代器实现->去直接访问它的内部的成员变量.

Ptr operator->()
{return &node->data;
}
template <class T ,class Ref,class Ptr>
struct list_iterator
{typedef List_Node<T> Node;typedef list_iterator<T,Ref,Ptr> self;

再这里也存在const对象的问题.我们仍然需要传一个模板参数.
具体参考代码
https://gitee.com/woodcola/c-learning-code/tree/master/list/list

相关文章:

list的使用以及模拟实现

本章目标 1.list的使用 2.list的模拟实现 1.list的使用 在stl中list是一个链表,并且是一个双向带头循环链表,这种结构的链表是最优结构. 因为它的实现上也是一块线性空间,它的使用上是与string和vector类似的.但相对的因为底层物理结构上它并不像vector是线性连续的,它并没有…...

java继承练习

//创建父类public class Employee {private String id;private String name;private double salary;public Employee() {}public Employee(String id, String name, double salary) {this.id id;this.name name;this.salary salary;}public String getId() {return id;}pu…...

猫咪如厕检测与分类识别系统系列【一】 功能需求分析及猫咪分类特征提取

开发背景 家里养了三只猫咪&#xff0c;其中一只布偶猫经常出入厕所。但因为平时忙于学业&#xff0c;没法时刻关注牠的行为。我知道猫咪的如厕频率和时长与健康状况密切相关&#xff0c;频繁如厕可能是泌尿问题&#xff0c;停留过久也可能是便秘或不适。为了更科学地了解牠的…...

sparkcore编程算子

今天是Spark Core编程算子 Value类型算子 1. map 将处理的数据逐条进行映射转换&#xff0c;这里的转换可以是类型的转换&#xff0c;也可以是值的转换。Map算子是分区内一个数据一个数据的执行&#xff0c;类似于串行操作。 特点&#xff1a; - 主要目的将数据源中的数据进行…...

【EI会议】第三届机器人与软件工程前沿国际会议(FRSE 2025)

第三届机器人与软件工程前沿国际会议&#xff08;FRSE 2025&#xff09;将于2025年8月8日-10日在中国张家界召开。会议由清华大学自动化系主办&#xff0c;长沙理工大学、湖南科技大学、吉首大学、AC学术中心协办。 一、会议信息 大会官网&#xff1a;www.icfrse.org 会议时…...

机器人系统仿真--1.机器人模型URDF

添加机器人地盘...

具身机器人中AI(DEEPSEEK)与PLC、驱动器协同发展研究:突破数据困境与指令精确控制(3)

具身机器人中AI&#xff08;DEEPSEEK&#xff09;与PLC、驱动器协同发展研究&#xff1a;突破数据困境与指令精确控制&#xff08;1&#xff09;-CSDN博客 具身机器人中AI&#xff08;DEEPSEEK&#xff09;与PLC、驱动器协同发展研究&#xff1a;突破数据困境与指令精确控制&a…...

+++++背到厌倦。持续更新

Spring IoC 的工作流程: 读取 BeanDefinition: Spring 容器启动时&#xff0c;会读取 Bean 的配置信息 (例如 XML 配置文件、注解或 Java 代码)&#xff0c;并将这些配置信息转换为 BeanDefinition 对象。创建 Bean 实例: 根据 BeanDefinition 中的信息&#xff0c;Spring 容器…...

修改 docker 工作目录

一、停掉 containerd、cri-docker、docker systemctl stop containerd systemctl stop cri-docker systemctl stop docker 二、拷贝 docker 工作目录下的所有文件到新路径 rsync -aP /var/lib/docker/ /docker/data/ 三、daemon.json 添加新工作目录路径 {"registry-…...

51c嵌入式~继电器~合集1

我自己的原文哦~ https://blog.51cto.com/whaosoft/13775821 一、继电器应用细节 继电器的应用&#xff0c;相信大家都知道&#xff0c;在电路中只要给它供电、断电也就可以工作了。本文讨论它的应用细节。 现在流行的接法 图中&#xff0c;继电器的线圈经过Q1作为开关&am…...

舵机:机器人领域的“关节革命者”

机器人的技术&#xff0c;每一个细微的进步都可能引领一场行业变革。而在这场变革中&#xff0c;舵机作为机器人关节的核心部件&#xff0c;正悄然上演着一场革命性的应用风暴。从简单的关节运动到复杂的姿态控制&#xff0c;舵机以其卓越的性能和无限的可能&#xff0c;重新定…...

飞书集成衡石ChatBot实战:如何10分钟搭建一个业务数据问答机器人?

让数据查询像聊天一样简单 在快节奏的业务环境中&#xff0c;数据查询的实时性和便捷性至关重要。传统BI工具需要复杂的操作&#xff0c;而衡石ChatBot结合飞书&#xff0c;让业务人员只需在聊天窗口提问&#xff0c;就能立刻获取数据反馈&#xff0c;真正实现“零门槛”数据分…...

高并发环境下超发现象的详细分析,包含场景示例、影响分析及解决方案(悲观锁、乐观锁、分布式锁)

以下是针对高并发环境下超发现象的详细分析&#xff0c;包含场景示例、影响分析及解决方案&#xff1a; 高并发下的超发详解 1. 超发现象定义 超发&#xff08;Over-issuance&#xff09;指在并发操作中&#xff0c;系统实际发放的资源&#xff08;如商品库存&#xff09;超过…...

Git 分支整合策略:Cherry-pick、Merge、Rebase 三者之间对比

Git 分支整合策略详解&#xff1a;Cherry-pick、Merge、Rebase 在日常的 Git 多分支协作开发中&#xff0c;代码合并是常见操作。Git 中主要提供以下三种方式来合并或迁移分支的提交&#xff1a; Cherry-pick&#xff1a;精确挑选部分提交复制到当前分支&#xff1b;Merge&am…...

嵌入式八股---计算机网络篇

前言 这块主要是结合着LWIP去理解计算机网络中常见的面试题 OSI四层/五层/七层模型 OSI分层&#xff08;7层&#xff09;&#xff1a;物理层、数据链路层、网络层、传输层、会话层(http)、表示层(加密)、应用层。 TCP/IP分层&#xff08;4层&#xff09;&#xff1a;网络接口层…...

使用 3D Layout 和 Icepak 进行 PCB、DCIR 和热分析

在本教程中&#xff0c;您将学习如何使用 3D Layout 执行 DCIR&#xff0c;然后使用功率损耗数据执行热分析。热分析将使用电子桌面 Icepak 进行。SIwave 及其嵌入式 icepak 可用于执行相同的分析&#xff0c;但有一个例外。电子桌面 Icepak 是一款功能齐全的 3D 工具。用户可以…...

UE5 Windows游戏窗口置顶

参考资料&#xff1a;UE5 UE4 项目设置全局置顶_ue4运行设置置顶-CSDN博客 修改完build.cs后&#xff0c;关掉重新生成解决方案。&#xff08;不然可能编译报错&#xff0c;在这卡了半个小时&#xff09; 不知道怎么用C的&#xff0c;可以用这个 Topmost - Keep Editor/Game w…...

【Linux】进程管理

一、程序与进程区别 1.程序&#xff1a; 存放在磁盘文件可执行文件&#xff08;静态存在&#xff09; 特点 静态性&#xff1a;程序是静态的&#xff0c;它只是一组指令的集合&#xff0c;在未被执行时&#xff0c;不会占用计算机的运行资源&#xff0c;也不会产生任何实际的…...

Android Studio PNG转SVG方法总结

在 Android Studio 中&#xff0c;将 PNG 位图转换为 SVG 矢量图并非直接内置的功能&#xff0c;但你可以通过以下步骤实现目标&#xff1a; 方法 1&#xff1a;使用在线转换工具 访问在线转换网站 推荐工具&#xff1a; CloudConvert Vector Magic OnlineConvertFree 上传…...

第6篇:Linux程序访问控制FPGA端LEDR<四>

Q&#xff1a;如何设计.c程序代码控制FPGA端外设LEDR动态显示&#xff1f; A&#xff1a;我们来设计程序实现简易计数器&#xff1a;将上一期点亮LEDR的程序代码*LEDR_ptr 0x2aa 改为 *LEDR_ptr *LEDR_ptr 1&#xff0c;读取LEDR端口的data寄存器&#xff0c;将寄存器值递增…...

DP扰码模块verilog仿真

在DisplayPort 1.4协议中&#xff0c;为了减少EMI&#xff0c;在8B/10B编码之前&#xff0c;需进行扰码Scramble。扰码用到了16-bit LFSR&#xff0c;表达式如下。 LFSR每移位8个bit后&#xff0c;用最高有效 8 位以相反的位顺序与一个字节数据进行异或从而实现数据加扰/解扰。…...

协作焊接机器人的应用场景

协作焊接机器人凭借其灵活性、安全性和高效性&#xff0c;在多个领域有着广泛的应用场景&#xff0c;以下是一些主要的方面&#xff1a; 汽车制造 车身焊接&#xff1a;在汽车车身生产线上&#xff0c;协作焊接机器人可与工人协同工作&#xff0c;完成车身各部件的焊接任务。例…...

深入解析计算机操作系统的底层架构与核心模块功能

深入解析计算机操作系统的底层架构与核心模块功能 一、操作系统底层架构总览 操作系统处于计算机系统的核心地位&#xff0c;是计算机硬件与用户之间的关键纽带&#xff0c;承担着资源管理者的重要角色。它负责统筹管理计算机的各类资源&#xff0c;如CPU、内存、存储设备以及…...

Elasticsearch 官网阅读学习笔记01

Elasticsearch 官网阅读学习笔记01 什么是 Elasticsearch&#xff1f; Elasticsearch 是位于 Elastic Stack 核心的分布式搜索和分析引擎。Elasticsearch 可为所有类型的数据提供近乎实时的搜索和分析。无论您拥有的是结构化或非结构化文本、数值数据还是地理空间数据 Elastic…...

玩转Docker | 使用Docker搭建Van-Nav导航站

玩转Docker | 使用Docker搭建Van-Nav导航站 前言一、Van-Nav介绍van-nav 简介主要特点二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署Van-Nav服务下载镜像创建容器检查容器状态检查服务端口安全设置四、访问Van-Nav应用访问Van-Nav首页登录后台管理五、添…...

若依 前后端部署

后端&#xff1a;直接把代码从gitee上拉去到本地目录 (https://gitee.com/y_project/RuoYi-Vue ) 注意下redis连接时password改auth 后端启动成功 前端&#xff1a;运行前首先确保安装了node环境&#xff0c;随后执行&#xff1a; &#xff01;&#xff01;一定要用管理员权限…...

笔记:头文件与静态库的使用及组织方式

笔记&#xff1a;头文件与静态库的使用及组织方式 1. 头文件的作用 接口声明&#xff1a;提供函数、类、变量等标识符的声明&#xff0c;供其他模块调用。编译依赖&#xff1a;编译器需要头文件来验证函数调用和类型匹配。避免重复定义&#xff1a;通过包含保护&#xff08;如…...

PostgreSQL-常用命令

PostgreSQL 提供了丰富的命令行工具和 SQL 命令&#xff0c;用于管理和操作数据库。以下是一些常用的命令和操作&#xff1a; 1. 数据库管理 创建数据库 CREATE DATABASE dbname; 删除数据库 DROP DATABASE dbname; 列出所有数据库 \l SELECT datname FROM pg_database;…...

如何在 Postman(测试工具) 中实现 Cookie 持久化并保持同一会话

在开发基于 Spring Boot 的 Web 应用时&#xff0c;使用 Session 存储验证码等敏感信息是常见的做法。然而&#xff0c;在调试接口时&#xff0c;你可能会遇到这样一个问题&#xff1a;第一次请求接口时存入的验证码在第二次请求时无法获取&#xff0c;原因往往是两个请求所使用…...

粘性定位(position:sticky)——微信小程序学习笔记

1. 简介 CSS 中的粘性定位&#xff08;Sticky positioning&#xff09;是一种特殊的定位方式&#xff0c;它可以使元素在滚动时保持在视窗的特定位置&#xff0c;类似于相对定位&#xff08;relative&#xff09;&#xff0c;但当页面滚动到元素的位置时&#xff0c;它会表现得…...

谷歌浏览器极速安装指南

目录 &#x1f4cb; 准备工作 步骤一&#xff1a;访问官网 &#x1f310; 步骤二&#xff1a;获取安装包 ⬇️ 步骤三&#xff1a;一键安装 &#x1f5b1;️ 步骤四&#xff1a;首次启动设置 ⚙️ 步骤五&#xff1a;开始探索&#xff01; &#x1f31f; &#x1f4ac; …...

【2024年最新IEEE Trans】模糊斜率熵Fuzzy Slope entropy及5种多尺度,应用于状态识别、故障诊断!

引言 2024年11月&#xff0c;研究者在测量领域国际顶级期刊《IEEE Transactions on Instrumentation and Measurement》&#xff08;IF 5.6&#xff0c;JCR 1区&#xff0c;中科院二区&#xff09;上发表科学研究成果&#xff0c;以“Optimized Fuzzy Slope Entropy: A Comple…...

无人机击落技术难点与要点分析!

一、技术难点 1. 目标探测与识别 小型化和低空飞行&#xff1a;现代无人机体积小、飞行高度低&#xff08;尤其在城市或复杂地形中&#xff09;&#xff0c;雷达和光学传感器难以有效探测。 隐身技术&#xff1a;部分高端无人机采用吸波材料或低可探测设计&#xff0c;进…...

Flink的数据流图中的数据通道 StreamEdge 详解

本文从基础原理到代码层面逐步解释 Flink 的数据通道 StreamEdge&#xff0c;尽量让初学者也能理解。 主要思路&#xff1a;从概念开始&#xff0c;逐步深入到实现细节&#xff0c;并结合伪代码来逐步推导。 第一步&#xff1a;什么是 StreamEdge&#xff1f; StreamEdge 是 F…...

OpenCV 图形API(25)图像滤波-----均值滤波(模糊处理)函数blur()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 使用归一化的方框滤波器模糊图像。 该函数使用以下核来平滑图像&#xff1a; K 1 k s i z e . w i d t h k s i z e . h e i g h t [ 1 1 ⋯ …...

基于频率约束条件的最小惯量需求评估,包括频率变化率ROCOF约束和频率最低点约束matlab/simulink

基于频率约束条件的最小惯量评估&#xff0c;包括频率变化率ROCOF约束和频率最低点约束matlab/simulink 1建立了含新能源调频的频域仿真传函模型&#xff0c;虚拟惯量下垂控制 2基于构建的模型&#xff0c;考虑了不同调频系数&#xff0c;不同扰动情况下的系统最小惯量需求...

.pdf,.docx,.doc文档在一页纸上显示4页内容(详细步骤)

生活中常见一页纸上显示4页内容&#xff0c;我们熟知的是打印文件时&#xff0c;选择“每页4版”&#xff0c;但如果也是为了方便阅读&#xff0c;想要设置成一张纸上显示4页内容&#xff0c;又该怎么做呢&#xff1f;下面分享.docx和.pdf文档&#xff0c;一张纸上显示4页内容的…...

基于CNN-BiLSTM-GRU的深度Q网络(Deep Q-Network,DQN)求解移动机器人路径规划,MATLAB代码

一、深度Q网络&#xff08;Deep Q-Network&#xff0c;DQN&#xff09;介绍 1、背景与动机 深度Q网络&#xff08;DQN&#xff09;是深度强化学习领域的里程碑算法&#xff0c;由DeepMind于2013年提出。它首次在 Atari 2600 游戏上实现了超越人类的表现&#xff0c;解决了传统…...

高并发场景下的 Java 性能优化

在当今数字化时代&#xff0c;高并发场景已成为众多 Java 应用面临的常态&#xff0c;如电商大促、在线直播等活动期间&#xff0c;系统需承受巨大的访问压力。因此&#xff0c;Java 性能优化在高并发场景下显得尤为重要。传统的人工编写代码优化方式不仅耗时费力&#xff0c;还…...

Java 设计模式:观察者模式详解

Java 设计模式&#xff1a;观察者模式详解 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了对象之间的一对多依赖关系&#xff0c;当一个对象的状态发生变化时&#xff0c;所有依赖它的对象都会收到通知并自动更新。这种模式广泛…...

Linux vagrant 导入Centos

前言 vagrant 导入centos 虚拟机 前提要求 安装 virtualbox 和vagrant<vagrant-disksize> (Linux 方式 Windows 方式) 创建一键部署centos 虚拟机 /opt/vagrant 安装目录/opt/VirtualBox 安装目录/opt/centos8/Vagrantfile &#xff08;可配置网络IP&#xff0c;内存…...

linux Ubuntu 如何删除文件,错误删除后怎么办?

一、删除文件的常用方法 命令行删除 普通删除&#xff1a;rm 文件名 &#xff08;示例&#xff1a;rm old_file.txt&#xff09; 强制删除&#xff08;无提示&#xff09;&#xff1a;rm -f 文件名 &#xff08;示例&#xff1a;rm -f locked_file.txt&#xff09; 删除目录…...

【前端】事件循环专题

引入 以下情况是为什么呢&#xff1f; //q1 for (var i 0; i < 3; i) {setTimeout(() > {console.log(i);}, 1000); } // console: // 3 // 3 // 3//q2 let name;setTimeout(() > {name name;console.log(name); }, 1000);if (name) {name newname;console.log(n…...

3DMAX笔记-UV知识点和烘焙步骤

1. 在展UV时&#xff0c;如何点击模型&#xff0c;就能选中所有这个模型的uv 2. 分多张UV时&#xff0c;不同的UV的可以设置为不同的颜色&#xff0c;然后可以通过颜色进行筛选。 3. 烘焙步骤 摆放完UV后&#xff0c;要另存为一份文件&#xff0c;留作备份 将模型部件全部分成…...

【深度学习】PyTorch实现VGG16模型及网络层数学原理

一、Demo概述 代码已附在文末 1.1 代码功能 ✅ 实现VGG16网络结构✅ 在CIFAR10数据集上训练分类模型 1.2 环境配置 详见【深度学习】Windows系统Anaconda CUDA cuDNN Pytorch环境配置 二、各网络层概念 2.1 卷积层&#xff08;nn.Conv2d&#xff09; nn.Conv2d(in_cha…...

Spring 事务

29.Spring管理事务的方式有几种&#xff1f; Spring中的事务分为编程式事务和声明式事务。 编程式事务是在代码中硬编码&#xff0c;通过 TransactionTemplate或者 TransactionManager 手动管理事务&#xff0c;事务范围过大会出现事务未提交导致超时&#xff0c;比较适合分布…...

GPT - TransformerDecoderBlock

本节代码定义了一个 TransformerDecoderBlock 类&#xff0c;它是 Transformer 架构中解码器的一个基本模块。这个模块包含了多头自注意力&#xff08;Multi-Head Attention&#xff09;、前馈网络&#xff08;Feed-Forward Network, FFN&#xff09;和层归一化&#xff08;Lay…...

【C语言】预处理(预编译)(C语言完结篇)

一、预定义符号 前面我们学习了C语言的编译和链接。 在C语言中设置了一些预定义符号&#xff0c;其可以直接使用&#xff0c;预定义符号也是在预处理期间处理的。 如下&#xff1a; 可以看到上面的预定义符号&#xff0c;其都有两个短下划线&#xff0c;要注意的是&#xff…...

【Kubernetes】Kubernetes 如何进行日志管理?Fluentd / Loki / ELK 适用于什么场景?

由于 Kubernetes 运行在容器化的环境中&#xff0c;应用程序和系统日志通常分布在多个容器和节点上&#xff0c;传统的日志管理方法&#xff08;例如直接访问每个节点的日志文件&#xff09;在 Kubernetes 中不适用。 因此&#xff0c;Kubernetes 引入了集中式日志管理方案&am…...

从 SaaS 到 MCP:构建 AI Agent 生态的标准化服务升级之路

从 SaaS 到 MCP&#xff1a;构建 AI Agent 生态的标准化服务升级之路 —— 以数据连接器 dslink 的技术改造实践为例 引言&#xff1a;AI Agent 时代的 SaaS 服务范式转型 在生成式 AI 爆发式发展的 2025 年&#xff0c;AI Agent 已从概念验证走向企业级应用落地&#xff0c;…...