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

数据结构之双链表

目录

1 简介

2 双链表的基本概念

2.1 节点结构

2.2 头插法和尾插法

3 代码实现 

4 代码解析(部分)

4.1 初始化双链表

4.2 添加节点

4.3 删除节点

4.4 获取节点

4.5 插入节点

4.6 反转链表

4.7 打印链表

4.8 核心操作分析

5 总结 


1 简介

双向链表(Doubly Linked List)是一种链式存储结构,每个节点包含数据域和前驱、后继指针,支持双向遍历。本代码实现了双向链表的初始化、插入、删除、查找、反转等操作,并维护头尾指针以优化性能。相比单链表,双向链表在插入和删除时无需额外查找前驱节点,适用于频繁修改数据结构的场景,如缓存管理、文本编辑器等。

2 双链表的基本概念

2.1 节点结构

双向链表的每个节点包含:

  • 数据域:存储数据

  • 前驱指针(prev):指向前一个节点

  • 后继指针(next):指向后一个节点

typedef struct node {int val;           // 数据域struct node* prev; // 前驱指针struct node* next; // 后继指针
} DListNode;

2.2 头插法和尾插法

  • 头插法:新节点插入链表头部,时间复杂度为 O(1)

  • 尾插法:新节点插入链表尾部,需维护尾指针,时间复杂度为 O(1)

3 代码实现 

// Dlink.c
// 双向链表
#include <stdio.h>
#include <stdlib.h>// 定义双链表节点
typedef struct node
{char data;         // 数据域struct node *prev; // 指针域(前驱节点)struct node *next; // 指针域(后继节点)
} Node;// 定义双链表
typedef struct list
{struct node *head; // 头指针struct node *tail; // 尾指针int size;          // 大小
} List;void init(List *list);
void add(List *list, char n);
void show(List *list);
void insert(List *list, int index, char n);
void insert2(Node *node, char n);
Node *get(List *list, int index);
void del(List *list, int index);
void reverse(List *list);int main(int argc, char const *argv[])
{List *list = malloc(sizeof(List));init(list);add(list, 'a');add(list, 'b');add(list, 'c');add(list, 'd');add(list, 'e');show(list);insert(list, 0, 'x');show(list);del(list, 5);show(list);reverse(list);show(list);return 0;
}// 反转链表
void reverse(List *list)
{Node *current = list->head->next; // 从第一个有效节点开始Node *prev = NULL;Node *next = NULL;list->tail = current; // 原头节点将成为新的尾节点while (current != NULL){next = current->next; // 保存下一个节点current->next = prev; // 反转当前节点的后继指针current->prev = next; // 反转当前节点的前驱指针prev = current;       // 更新前一个节点为当前节点current = next;       // 移动到下一个节点}list->head->next = prev; // 更新头节点的后继为新的头节点if (prev != NULL){prev->prev = list->head; // 更新新头节点的前驱为头节点}
}// 删除节点
void del(List *list, int index)
{if (index < 0 || index >= list->size) // 检查索引是否有效{return;}Node *node;if (index == 0) // 删除头节点的特殊情况{node = list->head->next;list->head->next = node->next;if (node->next != NULL){node->next->prev = list->head;}else{list->tail = list->head; // 如果删除的是唯一节点,更新尾指针}}else{node = get(list, index - 1); // 获取前驱节点Node *p = node->next;node->next = p->next;if (p->next != NULL){p->next->prev = node;}else{list->tail = node; // 如果删除的是尾节点,更新尾指针}node = p;}free(node);list->size--;
}// 获取节点
Node *get(List *list, int index)
{if (index < 0 || index >= list->size){return NULL;}if (index <= list->size / 2){Node *n = list->head;for (int i = 0; i <= index; i++){n = n->next;}return n;}else{Node *n = list->tail;for (int i = 1; i < list->size - index; i++){n = n->prev;}return n;}
}// 插入节点
void insert(List *list, int index, char n)
{Node *node = get(list, index );          // 获取要插入位置的前驱节点if (node == NULL){add(list, n);return;}Node *newN = malloc(sizeof(Node));newN->data = n;newN->prev = node->prev;newN->next = node;node->prev->next = newN;node->prev = newN;list->size++;
}// 插入节点
void insert2(Node *node, char n)
{Node *p = node->prev;Node *newN = malloc(sizeof(Node));newN->data = n;node->next = p->next;node->prev = p;p->next->prev = newN;p->next = newN;
}// 初始化双链表
void init(List *list)
{list->head = malloc(sizeof(Node));list->tail = malloc(sizeof(Node));list->tail = list->head; // 头尾指针指向同一个节点list->size = 0;
}// 添加节点
void add(List *list, char n)
{Node *node = malloc(sizeof(Node));node->data = n;node->prev = list->tail; // 新节点的前驱节点指向原来的尾节点node->next = NULL;       // 新节点的后继节点指向空list->tail->next = node; // 新节点成为最后一个节点(尾指针)的后继节点list->tail = node;       // 尾指针指向新节点list->size++;
}// 打印双链表
void show(List *list)
{printf("大小:%d\n", list->size);printf("链表:");Node *node = list->head->next;while (node != NULL){printf("->%c", node->data);node = node->next;}printf("\n");
}

4 代码解析(部分)

4.1 初始化双链表

void init(List *list) {list->head = malloc(sizeof(Node));  // 为头节点分配内存list->tail = malloc(sizeof(Node));  // 为尾节点分配内存list->tail = list->head;            // 头尾指针指向同一个节点,链表初始化为空list->size = 0;                     // 初始化链表大小为0
}

初始化双链表时,分配了头节点和尾节点的内存,并将头尾指针都指向同一个节点,表示链表为空,大小初始化为0。

4.2 添加节点

void add(List *list, char n) {Node *node = malloc(sizeof(Node));  // 为新节点分配内存node->data = n;                     // 将数据赋值给新节点node->prev = list->tail;            // 新节点的前驱指向当前尾节点node->next = NULL;                  // 新节点的后继指针为NULLlist->tail->next = node;            // 当前尾节点的后继指向新节点list->tail = node;                  // 更新尾指针指向新节点list->size++;                       // 更新链表大小
}

此函数向链表尾部添加一个新节点。首先为新节点分配内存,并设置数据域和前后指针。然后更新尾指针。

4.3 删除节点

void del(List *list, int index) {if (index < 0 || index >= list->size) {  // 检查索引是否有效return;}Node *node;if (index == 0) {  // 删除头节点的特殊情况node = list->head->next;list->head->next = node->next;if (node->next != NULL) {node->next->prev = list->head;} else {list->tail = list->head;  // 删除唯一节点时更新尾指针}} else {node = get(list, index - 1);  // 获取前驱节点Node *p = node->next;node->next = p->next;if (p->next != NULL) {p->next->prev = node;} else {list->tail = node;  // 删除尾节点时更新尾指针}node = p;}free(node);  // 释放删除节点的内存list->size--; // 更新链表大小
}

删除节点时,首先检查索引是否合法。删除头节点时直接更新头节点的 next,并更新尾节点指针(如果链表只剩一个节点)。删除其他节点时,获取前驱节点并更新前后节点的指针,释放节点内存并更新链表大小。

4.4 获取节点

Node *get(List *list, int index) {if (index < 0 || index >= list->size) {return NULL;}if (index <= list->size / 2) {  // 优化:从头部开始遍历Node *n = list->head;for (int i = 0; i <= index; i++) {n = n->next;}return n;} else {  // 优化:从尾部开始遍历Node *n = list->tail;for (int i = 1; i < list->size - index; i++) {n = n->prev;}return n;}
}

此函数根据给定索引获取节点。如果索引在链表的前半部分,则从头节点开始遍历;否则,从尾节点开始遍历,优化了查询性能。

4.5 插入节点

void insert(List *list, int index, char n) {Node *node = get(list, index); // 获取目标位置的前驱节点if (node == NULL) {             // 如果目标位置无效,调用add函数add(list, n);return;}Node *newN = malloc(sizeof(Node));  // 为新节点分配内存newN->data = n;                    // 设置数据域newN->prev = node->prev;           // 新节点的前驱指向目标节点的前驱newN->next = node;                 // 新节点的后继指向目标节点node->prev->next = newN;           // 前驱节点的后继指向新节点node->prev = newN;                 // 目标节点的前驱指向新节点list->size++;                      // 更新链表大小
}

插入节点时,首先获取目标位置的前驱节点。如果目标位置无效,则调用 add 函数将新节点添加到尾部。否则,分配新节点并将其插入到指定位置,更新前后节点的指针,并增加链表大小。

4.6 反转链表

void reverse(List *list) {Node *current = list->head->next; // 从第一个有效节点开始Node *prev = NULL;Node *next = NULL;list->tail = current; // 原头节点成为新的尾节点while (current != NULL) {next = current->next;  // 保存下一个节点current->next = prev;  // 反转当前节点的后继指针current->prev = next;  // 反转当前节点的前驱指针prev = current;        // 更新前驱节点current = next;        // 移动到下一个节点}list->head->next = prev; // 更新头节点的后继为新的头节点if (prev != NULL) {prev->prev = list->head;  // 更新新头节点的前驱为头节点}
}

此函数通过反转链表中的每个节点的前后指针来实现链表的反转,最后更新头尾节点指针。

4.7 打印链表

void show(List *list) {printf("大小:%d\n", list->size);  // 输出链表大小printf("链表:");Node *node = list->head->next;    // 从头节点的下一个节点开始遍历while (node != NULL) {printf("->%c", node->data);   // 输出节点的数据node = node->next;            // 移动到下一个节点}printf("\n");
}

此函数遍历链表并打印每个节点的 data 字段,帮助显示链表的内容。

4.8 核心操作分析

5 总结 

本文介绍了双向链表的基本概念及其在 C 语言中的实现,涵盖了链表的初始化、节点插入、删除、查找、反转等核心操作。双向链表相比单链表,能够支持双向遍历,具有更高的操作效率,特别是在插入和删除节点时不需要额外查找前驱节点。通过维护头尾指针,能够有效优化性能。通过对每个操作的详细解析,我们可以看到双向链表在动态数据结构中的应用价值,尤其在缓存管理、文本编辑等场景中,能够提高数据处理的灵活性和效率。

源码地址:0315/Dlink.c · jkh111/Niuer_C - 码云 - 开源中国

相关文章:

数据结构之双链表

目录 1 简介 2 双链表的基本概念 2.1 节点结构 2.2 头插法和尾插法 3 代码实现 4 代码解析&#xff08;部分&#xff09; 4.1 初始化双链表 4.2 添加节点 4.3 删除节点 4.4 获取节点 4.5 插入节点 4.6 反转链表 4.7 打印链表 4.8 核心操作分析 5 总结 1 简介 …...

dell 台式机 电脑 纽扣电池 如何取下?

dell 台式机 电脑 纽扣电池 如何取下&#xff1f; 戴尔-optiplex-3060-塔式机-服务手册...

JSON二次序列化问题分析

正常的JSON应该是: json Apply to VectorServic... { "id": "d471c19c-70eb-4f29-8604-b8284e8a9400", "text": "人为干预, 降低生产成本...", "metadata": { "chunkIndex": 2, …...

WebSocket 传输大量数据好不好?稳定不稳定

使用 WebSocket 传输大量数据 是可行的&#xff0c;但在实际应用中需要注意一些限制和优化策略。以下是关于 WebSocket 传输大量数据的详细分析&#xff1a; 1. WebSocket 传输大量数据的可行性 优点 实时性&#xff1a;WebSocket 是全双工通信协议&#xff0c;适合实时传输数…...

代码随想录刷题day52|(二叉树篇)106.从中序与后序遍历序列构造二叉树(▲

目录 一、二叉树理论知识 二、构造二叉树思路 2.1 构造二叉树流程&#xff08;给定中序后序 2.2 整体步骤 2.3 递归思路 2.4 给定前序和后序 三、相关算法题目 四、易错点 一、二叉树理论知识 详见&#xff1a;代码随想录刷题day34|&#xff08;二叉树篇&#xff09;二…...

无人设备遥控器之调度自动化技术篇

一、技术原理 信息采集与处理&#xff1a; 通过传感器、仪表等设备采集无人设备的各种数据&#xff0c;如位置、速度、状态等。 将采集到的数据传输到调度自动化系统中进行处理和分析&#xff0c;以获取设备的实时状态。 系统建模与优化&#xff1a; 调度自动化系统会根据…...

红宝书第十五讲:详解JavaScript迭代器与生成器:Symbol.iterator与yield

红宝书第十五讲&#xff1a;详解JavaScript迭代器与生成器&#xff1a;Symbol.iterator与yield 资料取自《JavaScript高级程序设计&#xff08;第5版&#xff09;》。 查看总目录&#xff1a;红宝书学习大纲 一、迭代器&#xff08;Iterator&#xff09;的“传送带”模式 迭代…...

【AI】NLP

不定期更新&#xff0c;建议关注收藏点赞。 目录 transformer大语言模型Google Gemma疫情网民情绪识别 整体框架 baseline构建 模型调参、模型优化、其他模型 数据trick、指标优化、magic feature 数据增强、伪标签、迁移学习 模型融合sklearn中TFIDF参数详解 频率阈值可以去掉…...

ENSP学习day10

NAT地址转换技术&#xff08;一&#xff09; NAT&#xff08;Network Address Translation&#xff09;地址转换技术是一种在计算机网络中常用的技术&#xff0c;在数据包从一个网络传输到另一个网络时&#xff0c;会对数据包中的源IP地址和目的IP地址进行修改的过程。这种技术…...

文件上传绕过的小点总结(4)

9.末尾点删除处理缺陷 给出源码&#xff1a; $file_name trim($_FILES[upload_file][name]); $file_name deldot($file_name);//删除文件名末尾的点 $file_ext strrchr($file_name, .); $file_ext strtolower($file_ext); //转换为小写 $file_ext str_ireplace(::$DATA,…...

实战-MySQL5.7升级8.0遇到的四个问题

近期几个项目的MySQL由5.7升级到8.0&#xff0c;升级过程中遇到四个问题&#xff0c;记录下来分享一下&#xff1a; 第一个问题详见之前的文章&#xff1a; MySQL 5.7升级8.0报异常&#xff1a;处理新增关键字 第二个问题详见之前的文章&#xff1a; MySQL 5.7升级8.0报异常…...

卷积神经网络的原理、实现及变体

卷积神经网络convolutional neural network&#xff0c;CNN 是为处理图像数据而生的网络&#xff0c;主要由卷积层&#xff08;填充和步幅&#xff09;、池化层&#xff08;汇聚层&#xff09;、全连接层组成。 卷积 虽然卷积层得名于卷积&#xff08;convolution&#xff09…...

java 线程创建Executors 和 ThreadPoolExecutor 和 CompletableFuture 三者 区别

Executors是一个线程池的工具类&#xff0c;而ThreadPoolExecutor是Executor接口的一个实现&#xff0c;是线程池的核心类。‌ Executors提供了多种快速创建线程池的方法&#xff0c;而ThreadPoolExecutor则提供了更高的自定义和控制能力‌。 Executors是一个工具类&#xff0…...

Redisson 实现分布式锁简单解析

目录 Redisson 实现分布式锁业务方法&#xff1a;加锁逻辑LockUtil 工具类锁余额方法&#xff1a;工具类代码枚举代码 RedisUtil 工具类tryLock 方法及重载【分布式锁具体实现】Supplier 函数式接口调用分析 Redisson 实现分布式锁 业务方法&#xff1a; 如图&#xff0c;简单…...

Python条件处理,新手入门到精通

Python条件处理&#xff0c;新手入门到精通 对话实录 **小白**&#xff1a;&#xff08;崩溃&#xff09;我写了if x 1:&#xff0c;为什么Python会报错&#xff1f; **专家**&#xff1a;&#xff08;推眼镜&#xff09;**是赋值&#xff0c;才是比较**&#xff01;想判断相…...

详细比较StringRedisTemplate和RedisTemplate的区别及使用方法,及解决融合使用方法

前言 感觉StringRedisTemplate和RedisTemplate非常的相识&#xff0c;到底有什么区别和联系呢&#xff1f;点开idea&#xff0c;打开其依赖关系&#xff0c;可以看出只需使用maven依赖包spring-boot-starter-data-redis&#xff0c;然后在service中注入StringRedisTemplate或者…...

开源模型应用落地-语音转文本-whisper模型-AIGC应用探索(五)

一、前言 在上一节中&#xff0c;学习了如何使用vLLM来部署Whisper-large-v3-turbo模型。不过&#xff0c;在实际使用时&#xff0c;模型一次只能处理30秒的音频。今天&#xff0c;将结合实际业务&#xff0c;介绍如何处理一段完整的音频&#xff0c;并生成相应的字幕文件。 相…...

python每日十题(10)

在Python语言中&#xff0c;源文件的扩展名&#xff08;后缀名&#xff09;一般使用.py。 保留字&#xff0c;也称关键字&#xff0c;是指被编程语言内部定义并保留使用的标识符。Python 3.x有35个关键字&#xff0c;分别为&#xff1a;and&#xff0c;as&#xff0c;assert&am…...

安装和部署Tomcat并在idea创建web文件

一、背景 实验任务为安装Tomcat并创建web文件 为提高安装效率并且通俗易懂&#xff0c;免得大量文字浪费时间&#xff0c;这里我们采用图片加文字的方式来给大家讲解这个安装教程。 二、安装过程 首先第一步一定要注意你是否下载了JDK&#xff0c;如果你是像我一样下载一个…...

【Linux】Ubuntu 24.04 LTS 安装 OpenJDK 8

目录 通过 apt-get 直接安装 JDK 1. 更新 apt 软件源 2. 检查 JDK 是否已安装 3. 安装OpenJDK 4. 检查 JDK 是否成功安装 5. 设置 JAVA_HOME 环境变量 找到需要设置的 Java 路径 使用文本编辑器打开/etc/environment文件 添加 Java 安装路径 应用更改和验证配置 通过…...

图灵300题-21~40-笔记002

图灵300题 图灵面试题视频&#xff1a;https://www.bilibili.com/video/BV17z421B7rB?spm_id_from333.788.videopod.episodes&vd_sourcebe7914db0accdc2315623a7ad0709b85&p20。 本文是学习笔记&#xff0c;如果需要面试没有时间阅读原博文&#xff0c;可以快速浏览笔…...

蓝桥杯--bfs专题第二个题目(leetcode103二叉树)

文章目录 1.题目概述2.思路分析3.代码分析 1.题目概述 这个题目是关于二叉树的锯齿形的遍历&#xff1a;这个锯齿形是什么意思呢&#xff1f;简单的通俗的解释&#xff0c;就是S型的&#xff0c;例如下面的这个示例里面的二叉树&#xff1a; 第一行从左到右&#xff1a;但是只…...

React 知识回顾(HOC、合成事件、Fiber)

HOC 嗯&#xff0c;用户问的是HOC是什么以及它能用来做什么。我需要先理解HOC的基本概念&#xff0c;然后整理它的用途。根据搜索结果&#xff0c;HOC是React中的高阶组件&#xff0c;用来复用逻辑。网页1提到HOC是一个函数&#xff0c;接收组件返回新组件&#xff0c;属于设计…...

s1: Simple test-time scaling 【论文阅读笔记】

s1: Simple test-time scaling 关于test-time scaling 这个概念其实是相对 train scaling而言的。train scalling 指的是增加训练数据&#xff0c;增加训练flops等等&#xff0c;投入更多资源在train上。test-time scaling&#xff0c;其实现在简化点的理解&#xff0c;就是 …...

基于 Milvus 和 BiomedBERT 的医学文献智能搜索系统

前言 随着医学研究的不断深入&#xff0c;文献数量呈爆炸式增长&#xff0c;如何快速从海量文献中提取关键信息成为一大挑战。最近&#xff0c;我基于 Milvus 向量数据库和 BiomedBERT 嵌入模型&#xff0c;开发了一个智能搜索系统&#xff0c;支持语义搜索和关键词匹配&#…...

ASP.NET Web的 Razor Pages应用,配置热重载,解决.NET Core MVC 页面在更改后不刷新

Razor Pages应用&#xff0c;修改页面查看修改效果&#xff0c;如果没有热重载&#xff0c;改一句话跑一次&#xff0c;这个活就没法干了。 1、VS2022中的NuGet中安装RuntimeCompilation Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation 需要配套你的.net sdk版本&#x…...

MySQL 对text类型字段添加索引

对于 MySQL 中的 text 类型字段&#xff0c;可以通过以下步骤向其添加索引&#xff1a; 创建辅助字段&#xff1a;创建一个辅助字段&#xff0c;将该字段的一部分数据转移到辅助字段中。例如&#xff0c;可以创建一个 varchar 类型的字段来存储 text 字段的前缀。 添加索引&am…...

深入解析SQL2API平台:数据交互革新者

在数字化转型持续深入的当下&#xff0c;企业对数据的高效利用与管理的需求愈发迫切。SQL2API平台应运而生&#xff0c;成为助力企业突破数据交互困境的有力工具&#xff0c;特别是它由麦聪软件基于DaaS&#xff08;数据即服务&#xff09;产品创新衍生而来&#xff0c;备受业界…...

@Autowired 和 @Resource 注解的区别

前言 Autowired 和 Resource 是 Spring 中用于依赖注入的注解&#xff0c;但两者在实现机制和使用方式上有显著差异。 主要区别 1.来源不同 Autowired&#xff1a;由 Spring 框架提供&#xff08;org.springframework.beans.factory.annotation&#xff09;&#xff0c;与 S…...

稳定运行的以ElasticSearch数据库为数据源和目标的ETL性能变差时提高性能方法和步骤

在使用 Elasticsearch 作为数据源和目标的 ETL&#xff08;Extract, Transform, Load&#xff09;过程中&#xff0c;性能逐渐变差的原因可能有很多&#xff0c;比如查询效率下降、集群负载过高、资源配置不合理等。 性能的提升通常需要从多个方面入手&#xff0c;尤其是在处理…...

游戏引擎学习第182天

回顾和今天的计划 昨天的进展令人惊喜&#xff0c;原本的调试系统已经被一个新的系统完全替换&#xff0c;新系统不仅能完成原有的所有功能&#xff0c;还能捕获完整的调试信息&#xff0c;包括时间戳等关键数据。这次的替换非常顺利&#xff0c;效果很好。 今天的重点是在此基…...

EJS缓存解决多页面相同闪动问题

基于 EJS 的模板引擎特性及其缓存机制&#xff0c;以下是关于缓存相同模块的详细解答&#xff1a; 一、EJS 缓存机制的核心能力 模板编译缓存 EJS 默认会将编译后的模板函数缓存在内存中&#xff0c;当相同模板文件被多次渲染时&#xff0c;会直接复用已编译的模板函数&#x…...

【MySQL】mysql日志文件

目录 日志文件特征 错误日志&#xff08;Error log &#xff09; 常规查询日志&#xff08;General query log &#xff09; 慢速查询日志&#xff08;Slow query log &#xff09; 审计日志&#xff08;Audit log &#xff09; 二进制日志&#xff08;Binary log &#…...

【C++】STL性能优化实战

STL性能优化实战 STL (Standard Template Library) 是 C 标准库的核心部分&#xff0c;提供了各种容器、算法和迭代器。虽然 STL 提供了强大的功能&#xff0c;但不恰当的使用可能导致性能问题。下面我将详细介绍 STL 性能优化的实战技巧&#xff0c;并通过具体案例说明。 1.…...

Playwright + MCP:用AI对话重新定义浏览器自动化,效率提升300%!

一、引言&#xff1a;自动化测试的“瓶颈”与MCP的革新 传统自动化测试依赖开发者手动编写脚本&#xff0c;不仅耗时且容易因页面动态变化失效。例如&#xff0c;一个简单的登录流程可能需要开发者手动定位元素、处理等待逻辑&#xff0c;甚至反复调试超时问题。而MCP&#xf…...

12-scala样例类(Case Classes)

例类&#xff08;Case classes&#xff09;和普通类差不多&#xff0c;只有几点关键差别&#xff0c;接下来的介绍将会涵盖这些差别。样例类非常适合用于不可变的数据。 定义一个样例类 一个最简单的样例类定义由关键字case class&#xff0c;类名&#xff0c;参数列表&#…...

WPF 与 C# 开发深度剖析

一、引言 在当今的软件开发领域&#xff0c;Windows 平台依旧占据着重要的地位。而 WPF&#xff08;Windows Presentation Foundation&#xff09;作为微软推出的一款强大的用户界面&#xff08;UI&#xff09;框架&#xff0c;为开发者提供了丰富的功能和灵活的设计方式&…...

【工具使用-编译器】VScode(Ubuntu)使用

1. VScode的快捷键 快捷键功能说明Ctrl+Shift+P / F1显示命令面板Ctrl+P快速打开文件Ctrl+Shift+N新建窗口Ctrl+Shift+W关闭窗口Ctrl+,打开设置Ctrl+K Ctrl+S打开快捷键设置Ctrl+X剪切行(无选中时剪切整行)Ctrl+C复制行(无选中时复制整行)Alt+↑ / Alt+↓向上/向下移动行Sh…...

C# SerialPort 使用详解

总目录 前言 在工业控制、物联网、嵌入式开发等领域&#xff0c;串口通信&#xff08;Serial Port Communication&#xff09;是连接串行设备&#xff08;如条码扫描器、GPS接收器等&#xff09;与计算机的重要手段。C# 提供了内置的 SerialPort 类&#xff0c;简化了串口开发…...

数据结构--二叉排序树

一、二叉排序树的定义 二叉排序树&#xff0c;又称二叉查找树。 性质&#xff1a; 左子树结点值<根结点值<右子树结点值&#xff08;进行中序遍历&#xff0c;可以得到一个递增的有序序列&#xff09; 二、查找操作 利用二叉排序树的性质&#xff0c;如果树空&#xff0c…...

FPGA的直方图均衡

文章目录 一、直方图均衡二、代码实现三、仿真 一、直方图均衡 直方图均衡&#xff08;Histogram Equalization&#xff09;是一种用于增强图像对比度的图像处理技术。它通过重新分配图像像素的灰度值&#xff0c;使得图像的灰度直方图在整个灰度范围内均匀分布&#xff0c;从而…...

使用Python将视频转化为gif

使用Python将视频转化为gif 一、前言二、准备三、测试 一、前言 最近想把喜欢的视频片段作成gif&#xff0c;就试着用Python做了下&#xff0c;感觉效果还行&#xff0c;这里做个记录。 二、准备 先下载安装对应的库&#xff0c;命令如下&#xff1a; pip install moviepy …...

基于javaweb的SpringBoot雪具商城系统设计与实现系统(源码+文档+部署讲解)

​ 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、…...

Harbor镜像仓库迁移与高可用集群搭建HTTPS实现实战指南

实验环境 Ubuntu22.04操作系统 registry节点 10.0.0.91 master节点 10.0.0.92 backup节点 10.0.0.93 在企业信息化建设的不同演进阶段&#xff0c;私有镜像仓库的选型策略存在显著差异。近期主导完成某企业级容器镜像仓库升级项目&#xff0c;成功实现Docker Registry至Ha…...

redis--JavaSpring客户端

目录 一、引言 二、配置 三、相关操作 四、总结 一、引言 本篇文章会将redis与spring项目进行结合&#xff0c;看看再spring项目中&#xff0c;redis是如何使用的 二、配置 三、相关操作 四、总结 在spring项目中的使用和在基础项目上的使用有差异&#xff0c;但是差异并不大…...

JavaWeb3

聚合函数&#xff1a;把某一列的数据计算。count,max,min,avg,sum select count(id) from wife;-- 统计个数&#xff0c;不计算null&#xff0c;统计常量表示个数 select count(*) from wife; select min(id) from wife; select avg(age) from wife; 分组查询 select name,c…...

SAP-ABAP:SAP数据集成全场景技术指南(BAPI、RFC、IDOC、BATCHJOB、ODATA、WEBSERVICE):从实时交互到批量处理

SAP数据集成全场景技术指南:从实时交互到批量处理 #mermaid-svg-hpPMerJYUerla0BJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-hpPMerJYUerla0BJ .error-icon{fill:#552222;}#mermaid-svg-hpPMerJYUerla0BJ .er…...

QT笔记----QCheckBox

文章目录 概要1、QCheckBox 的基本概念2、单个QCheckBox3、多个QCheckBox同时应用3.1、实现效果3.2、实现Demo 概要 在 Qt 应用程序开发中&#xff0c;QCheckBox 是一个常用的用户界面元素&#xff0c;它允许用户在两种状态&#xff08;选中和未选中&#xff09;之间进行切换&a…...

试试智能体工作流,自动化搞定运维故障排查

APO 1.5.0版本全新推出的智能体工作流功能&#xff0c;让运维经验不再零散&#xff01;只需将日常的运维操作和故障排查经验转化为标准化流程&#xff0c;就能一键复用&#xff0c;效率翻倍&#xff0c;从此告别重复劳动&#xff0c;把时间留给更有价值的创新工作。更贴心的是&…...

3.24[Q]Linux

我正在学习Linux&#xff0c;Linux设备管理是怎样的&#xff1f;详细解释&#xff0c;越细节越好 我正在学习Linux&#xff0c;在Linux设备管理中&#xff0c;什么是char device&#xff1f;以及block,usb device?详细解释&#xff0c;越细节越好 我正在学习Linux&#xff0…...