链表结构深度解析:从单向无头到双向循环的实现全指南
上篇博客实现动态顺序表时,我们会发现它存在许多弊端,如:
• 中间/头部的插⼊删除,时间复杂度为O(N)• 增容需要申请新空间,拷⻉数据,释放旧空间。会有不⼩的消耗。• 增容⼀般是呈2倍的增⻓,势必会有⼀定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插⼊了5个数据,后⾯没有数据插⼊了,那么就浪费了95个数据空间。
这些问题该怎么解决呢?
我们需要学习线性表的另一种实现方式--链表。
目录
1.链表的分类
2.单链表
2.1概念与结构
2.1.1结点
2.1.2链表的性质
2.2单链表的实现
2.2.1 SList.h
2.2.2 SList.c
3.双向链表
3.1.概念与结构
3.2双向链表的实现
3.2.1List.h
3.2.2 List.c
4.顺序表与链表比较
1.链表的分类
链表的结构⾮常多样,以下情况组合起来有8种(2 x 2 x 2)链表结构:
链表可从三个维度分类组合:
- 单向与双向:
- 单向链表:结点仅含一个指向下一结点的指针;
- 双向链表:结点含前驱、后继两个指针。
- 带头与不带头:
- 带头链表有专门头结点(不存数据),便于操作;
- 不带头链表首个结点即数据结点。
- 循环与不循环:
- 循环链表:最后结点指针指向头结点(带头)或首结点(不带头);
- 不循环链表:最后结点指针为
null
(单向)或后继为null
且首结点前驱为null
(双向)。
2.单链表
2.1概念与结构
2.1.1结点
2.1.2链表的性质
1、链式机构在逻辑上是连续的,在物理结构上不⼀定连续2、结点⼀般是从堆上申请的3、从堆上申请来的空间,是按照⼀定策略分配出来的,每次申请的空间可能连续,可能不连续
struct SListNode {int data; //结点数据struct SListNode* next; //指针变量⽤保存下⼀个结点的地址
};
2.2单链表的实现
注意:以下函数的一些参数有一些是二级指针,不是一级指针,使用时要格外注意。使用二级指针是因为要改变实参(使用一级指针的话,形参的变化影响不了实参)。
2.2.1 SList.h
#pragma once#include<stdio.h>
#include<assert.h>
#include<stdlib.h>typedef int SLTDataType;typedef struct SListNode
{SLTDataType data; //结点数据struct SListNode* next; //指针保存下⼀个结点的地址
}SLTNode;void SLTPrint(SLTNode * phead);//头部插⼊删除/尾部插⼊删除
void SLTPushBack(SLTNode * *pphead, SLTDataType x);
void SLTPushFront(SLTNode * *pphead, SLTDataType x);void SLTPopBack(SLTNode * *pphead);
void SLTPopFront(SLTNode * *pphead);//查找
SLTNode * SLTFind(SLTNode * phead, SLTDataType x);//在指定位置之前插⼊数据
void SLTInsert(SLTNode * *pphead, SLTNode * pos, SLTDataType x);//删除pos结点
void SLTErase(SLTNode * *pphead, SLTNode * pos);//在指定位置之后插⼊数据
void SLTInsertAfter(SLTNode * pos, SLTDataType x);//删除pos之后的结点
void SLTEraseAfter(SLTNode * pos);//销毁链表
void SListDestroy(SLTNode * *pphead);
2.2.2 SList.c
2.2.2.1创建结点,打印链表,销毁链表
#define _CRT_SECURE_NO_WARNINGS#include "SList.h"// 测试函数:手动创建并遍历一个单链表,最后释放内存
void test1()
{// 手动创建4个节点并初始化数据(实际开发中建议封装成函数)SLTNode* n1 = (SLTNode*)malloc(sizeof(SLTNode));n1->data = 1; // 节点1数据赋值为1SLTNode* n2 = (SLTNode*)malloc(sizeof(SLTNode));n2->data = 2; // 节点2数据赋值为2SLTNode* n3 = (SLTNode*)malloc(sizeof(SLTNode));n3->data = 3; // 节点3数据赋值为3SLTNode* n4 = (SLTNode*)malloc(sizeof(SLTNode));n4->data = 4; // 节点4数据赋值为4// 手动连接节点形成链表:1 -> 2 -> 3 -> 4 -> NULLn1->next = n2;n2->next = n3;n3->next = n4;n4->next = NULL; // 链表终止标志// 遍历链表并打印数据SLTNode* pcur = n1; // 从链表头节点开始遍历while (pcur){printf("%d ", pcur->data); // 打印当前节点数据pcur = pcur->next; // 移动到下一个节点}printf("\n"); // 打印换行// 安全释放链表内存(防止内存泄漏)SLTNode* current = n1; // 重新从头节点开始while (current){SLTNode* temp = current; // 临时保存当前节点地址current = current->next; // 先移动到下一个节点free(temp); // 释放当前节点内存}// 注意:此时n1~n4已成为野指针,不可再访问
}int main()
{test1(); // 执行测试函数return 0;
}
封装函数:
1.创建结点:
SLTNode* CreateNode(int data)
{SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));if (node == NULL){perror("malloc");exit(EXIT_FAILURE);}node->data = data;node->next = NULL;return node;
}
2.打印链表
void SLTPrint(SLTNode* phead)
{assert(phead);SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}
3.销毁链表
void SListDestroy(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* current = *pphead;while (current){SLTNode* temp = current;current = current->next;free(temp);}*pphead = NULL;
}
2.2.2.2尾部插入删除
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* new_node = CreateNode(x);if (*pphead == NULL){*pphead = new_node;}else{SLTNode* pcur = *pphead;while (pcur->next){pcur = pcur->next;}pcur->next = new_node;}
}void SLTPopBack(SLTNode** pphead)
{assert(pphead && *pphead);if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{SLTNode* tail = *pphead;while (tail->next->next){tail = tail->next;}free(tail->next);tail->next = NULL;}
}
2.2.2.3头部插入删除
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* new_node = CreateNode(x);new_node->next = *pphead;*pphead = new_node;
}void SLTPopFront(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* tem = (*pphead)->next;free(*pphead);*pphead = tem;
}
2.2.2.3查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{assert(phead);SLTNode* pcur = phead;while (pcur){if (pcur->data = x){return pcur;}pcur = pcur->next;}return NULL;
}
2.2.2.4在指定位置插入删除
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);assert(pos);if (*pphead == pos){SLTPushFront(pphead,x);}else{SLTNode* new_node = CreateNode(x);SLTNode* pcur = *pphead;while (pcur->next != pos){pcur = pcur->next;}pcur->next = new_node;new_node->next = pos;}
}void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* new_node = CreateNode(x);new_node->next = pos->next;pos->next = new_node;
}void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && *pphead);if (*pphead == pos){SLTPopFront(pphead);}else{SLTNode* pcur = *pphead;while (pcur->next != pos){pcur = pcur->next;}pcur->next = pos->next;free(pos);pos = NULL;}
}void SLTEraseAfter(SLTNode* pos)
{assert(pos);SLTNode* del = pos->next;pos->next = pos->next->next;free(del);del = NULL;
}
3.双向链表
3.1.概念与结构
带头双向循环链表是一种具有特定结构与特性的线性数据结构。其每个节点包含三部分:数据域(存储实际数据)、前驱指针(
prev
,指向前驱节点)与后继指针(next
,指向后继节点),以此实现双向链接。链表存在一个头结点(通常为哨兵节点,不存储有效数据),尾节点的next
指针指向头结点,头结点的 prev 指针指向尾节点,构成循环结构。从结构细节看:
- 头结点(head):作为链表起始点,
next
指向首个数据节点(如d1
),prev 指向尾节点(如d3
)。- 数据节点(如
d1
、d2
、d3
):
d1
的 prev 指向头结点head
,next
指向d2
;d2
的 prev 指向d1
,next
指向d3
;- 尾节点(
d3
):next
指向头结点head
,prev 指向d2
。
typedef int LTDataType;typedef struct listNode {LTDataType data;struct listNode* next;struct listNode* prev;
}LTNode;
3.2双向链表的实现
3.2.1List.h
#pragma once#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int LTDataType;typedef struct listNode {LTDataType data;struct listNode* next;struct listNode* prev;
}LTNode;LTNode* CreateNode(LTDataType x);//初始化
LTNode* LTInit2();
void LTInit1(LTNode** pphead);//打印链表
void LTPrint(LTNode* phead);//判断链表是否为空
bool LTEmpty(LTNode* phead);//尾插及尾删
void LTPushBack(LTNode* phead, LTDataType x);
void LTPopBack(LTNode* phead);//头插及头删
void LTPushFront(LTNode* phead, LTDataType x);
void LTPopFront(LTNode* phead);//查找
LTNode* LTFind(LTNode* phead, LTDataType x);//在pos位置之后插⼊数据
void LTInsert(LTNode* pos, LTDataType x);//删除pos结点
void LTErase(LTNode* pos);//销毁链表
void LTDestroy(LTNode* phead);
3.2.2 List.c
3.2.2.1初始化链表,创建结点,打印链表,判断链表是否无有效数据
LTNode* CreateNode(LTDataType x)
{LTNode* new_node = (LTNode*)malloc(sizeof(LTNode));if (new_node == NULL){perror("malloc");exit(1);}new_node->data = x;new_node->prev = new_node->next = new_node;return new_node;
}void LTInit1(LTNode** pphead)
{assert(pphead);*pphead = CreateNode(-1);
}LTNode* LTInit2()
{LTNode* phead = CreateNode(-1);return phead;
}void LTPrint(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){printf("%d ", pcur->data);pcur = pcur->next;}printf("\n");
}bool LTEmpty(LTNode* phead)
{assert(phead);return phead->next == phead;
}
3.2.2.2尾插及尾删
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);//phead->prev new_node pheadLTNode* new_node = CreateNode(x);new_node->next = phead;new_node->prev = phead->prev;phead->prev->next = new_node;phead->prev = new_node;
}void LTPopBack(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));//phead->prev->prev phead->prev pheadLTNode* del = phead->prev;del->prev->next = phead;phead->prev = del->prev;free(del);
}
尾插

尾删
3.2.2.3头插及头删
void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* new_node = CreateNode(x);//phead new_node phead->nextnew_node->next = phead->next;new_node->prev = phead;phead->next->prev = new_node;phead->next = new_node;
}void LTPopFront(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTNode* del = phead->next;del->next->prev = phead;phead->next = del->next;free(del);del = NULL;
}

头插

头删
3.2.2.4查找,在指定位置插入及删除
LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){if (pcur->data == x){return pcur;}pcur = pcur->next;}return NULL;
}//在pos位置之后插⼊数据
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* new_node = CreateNode(x);new_node->next = pos->next;new_node->prev = pos;pos->next->prev = new_node;pos->next = new_node;
}void LTErase(LTNode* pos)
{assert(pos);assert(!(pos->prev == pos && pos->next == pos));pos->next->prev = pos->prev;pos->prev->next = pos->next;free(pos);
}

在指定位置之后插入

删除指定位置结点
3.2.2.5销毁链表
void LTDestroy(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){LTNode* del = pcur;pcur = pcur->next;free(del);}free(phead);
}
4.顺序表与链表比较
不同点 | 顺序表 | 链表(单链表) |
存储空间上 | 物理上⼀定连续 | 逻辑上连续,但物理上不⼀定连续 |
随机访问 | ⽀持O(1) | 不⽀持:O(N) |
任意位置插⼊或者删除元素 | 可能需要搬移元素,效率低O(N) | 只需修改指针指向 |
插⼊ | 动态顺序表,空间不够时需要扩容和空间浪费 | 没有容量的概念,按需申请释放,不存在空间浪费 |
应⽤场景 | 元素⾼效存储+频繁访问 | 任意位置⾼效插⼊和删除 |
相关文章:
链表结构深度解析:从单向无头到双向循环的实现全指南
上篇博客实现动态顺序表时,我们会发现它存在许多弊端,如: • 中间/头部的插⼊删除,时间复杂度为O(N) • 增容需要申请新空间,拷⻉数据,释放旧空间。会有不⼩的消耗。 • 增容⼀般是呈2倍的增⻓,…...
Apache Velocity代码生成简要介绍
Apache Velocity 概述 Apache Velocity 是一个基于 Java 的模板引擎,它允许将 Java 代码与 HTML、XML 或其他文本格式分离,实现视图与数据的解耦。在 Web 开发中,Velocity 常用于生成动态网页内容;在其他场景下,也可用…...
阿里云前端Nginx部署完,用ip地址访问却总访问不到,为什么?检查安全组是否设置u为Http(80)!
根据你的描述,Ping测试显示数据包无丢失但无法通过公网IP访问服务,说明网络基础层(ICMP协议)是通畅的,但更高层(如TCP/UDP协议或服务配置)存在问题。以下是系统性排查与解决方案: 一…...
【Hive入门】Hive行级安全:基于Apache Ranger的细粒度访问控制深度解析
引言 在大数据时代,数据安全与隐私保护已成为企业不可忽视的核心需求。传统表级权限控制已无法满足"同一张表不同用户看到不同数据"的业务场景,行级安全(Row-Level Security)成为数据仓库系统的必备能力。 1 行级安全概述 1.1 什么是行级安全…...
Marin说PCB之1000-BASE-T1的PCB设计总结--04
另外一路的1000-BASE-T1 Circuit:千兆以太网的仿真电路原理图的连接搭建方式如下: (共模电感的连接需要特别注意一下PIN序别搞错了) 这一路1000-BASE-T1 Circuit是做了兼容设计的: 其中电容C2099和C2100是百兆以太网的…...
两数之和(暴力+哈希查找)
目录 一.题目 二.解题过程 题目解析 方法一(暴力求解) 思路 代码 提交结果 方法二(哈希查找) 思路 代码 提交结果 作者的个人gitee 作者的算法讲解主页▶️ 每日一言:“愿你纵踩淤泥,也要…...
Qt项目——天气预报
目录 前言结果预览工程文件窗体无状态栏窗口跟随移动HTTP基本概念JSON数据QT解析JSON数据结语 前言 通过对之前Qt的学习其实我们就已经有一点经验了,做天气预报只需要了解以下内容: stylesheet界面美化 Json数据解析 HTTP通信 自定义控件绘制温度 结果预…...
智能推理DeepSeek-R1+Word深度整合业级智能办公构建
前引: 当我们将DeepSeek-R1深度集成到Word时,实际上是在构建智能办公的"数字神经系统"。这个系统不仅理解文字内容,更能感知用户意图,在恰当的时刻提供精准的智能辅助。随着RAG(检索增强生成)技术…...
【C++ Qt】常用输入类下:Combo Box/Spin Box/DataTimeEdit/Dial/Slide
每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” 绪论: 在Qt开发框架中,UI组件是构建用户交互界面的基石。本章将详细探讨Qt中常用的UI组件,包括下拉框(QComboBoxÿ…...
基于Piecewise Jerk Speed Optimizer的速度规划算法(附ROS C++/Python仿真)
目录 1 时空解耦运动规划2 PJSO速度规划原理2.1 优化变量2.2 代价函数2.3 约束条件2.4 二次规划形式 3 算法仿真3.1 ROS C仿真3.2 Python仿真 1 时空解耦运动规划 在自主移动系统的运动规划体系中,时空解耦的递进式架构因其高效性与工程可实现性被广泛采用。这一架…...
K8s 常用命令、对象名称缩写汇总
K8s 常用命令、对象名称缩写汇总 前言 在之前的文章中已经陆续介绍过 Kubernetes 的部分命令,本文将专题介绍 Kubernetes 的常用命令,处理日常工作基本够用了。 集群相关 1、查看集群信息 kubectl cluster-info # 输出信息Kubernetes master is run…...
C++编程语言:从高效系统开发到现代编程范式的演进之路
目录 前言一、c简介1.1 起源1.2 c的特点 二、开发环境搭建 2.1. 安装 Qt 开发工具2.2 修改编码环境 2.3创建第一个 Qt 项目2.4 c的编译过程2.5 代码示例 2.6 qt疑难杂症 2.6.1 遇到无法删除代码,一点击光标就变成小黑块2.6.2 遇到运行不弹出终端 编辑 2.6.3 遇到…...
OpenCV进阶操作:角点检测
文章目录 一、角点检测1、定义2、检测流程1)输入图像2)图像预处理3)特征提取4)角点检测5)角点定位和标记6)角点筛选或后处理(可选)7)输出结果 二、Harris 角点检测&#…...
广州华锐视点邀您参与2025广交会VRAR展【5月10-12日】
2025 广交会数字显示与元宇宙生态博览会暨第 9 届世界 VR&AR 展将在广州盛大举行 。时间:2025 年 5 月 10 日至 12 日,广州华锐视点作为一家深耕 VR、AR、AI、元宇宙内容制作领域的企业,也将携旗下众多创新产品和解决方案闪耀登场&#x…...
mac m2 安装 hbase
默认安装好了 homebrew。 1. 终端先更新下 homebrew brew upgrade再安装 hbase brew install hbase 安装完会有如下图的内容 2. 按照提示启动 hbase brew services start hbase返回启动成功 3. 访问 http://localhost:16010 检验一下 启动成功 4. 在启动 hbase shell之…...
k8s node 报IPVS no destination available
在 Kubernetes 集群中,IPVS no destination available 错误通常表示 kube-proxy(IPVS 模式)无法为 Service 找到可用的后端 Pod。这会导致流量无法正确转发,影响服务可用性。以下是详细的排查和解决方法: 一、错误原因…...
MySQL 中 EXISTS (SELECT 1 FROM ...) 的用法详解
EXISTS (SELECT 1 FROM ...) 是 MySQL 中用于存在性检查的核心语法,其核心逻辑是判断子查询是否返回至少一行数据。以下从作用原理、使用场景、性能优化等方面展开解析,并结合具体示例说明。 1. 基本语法与作用原理 语法结构: SELECT 列名 F…...
荣耀A8互动娱乐组件部署实录(第3部分:控制端结构与房间通信协议)
作者:曾在 WebSocket 超时里泡了七天七夜的苦命人 一、控制端总体架构概述 荣耀A8控制端主要承担的是“运营支点”功能,也就是开发与运营之间的桥梁。它既不直接参与玩家行为,又控制着玩家的行为逻辑和游戏规则触发机制。控制端的主要职责包…...
前端-HTML+CSS+JavaScript+Vue+Ajax概述
HTML(超文本标记语言)常见标签 <html><head> <title>这是标题的内容,显示在浏览器的头部</title></head><body><!-- 这里面的内容在浏览器显示给用户看 --><!-- h1 -> h6 : 标题从大到小 …...
20250506格式化NanoPi NEO开发板使用Ubuntu core16.04系统的TF启动卡
https://www.sdcard.org/downloads/formatter/eula_windows/SDCardFormatterv5_WinEN.zip 20250506使用SDCardFormatter工具格式化NanoPi NEO开发板使用Ubuntu core16.04系统的TF启动卡 2025/5/6 20:04 缘起:使用友善之臂的NanoPi NEO开发板,制作了Ubunt…...
信息时代的政治重构:网络空间与主权的未来
一、网络空间:暴力垄断的终结 无边界主权的崛起 网络空间作为“第五阶段”的暴力竞争场域,打破传统领土垄断。政府无法像控制物理世界那样垄断网络暴力,类似公海的法律真空状态。 边区类比:中世纪的安道尔(法西共管避…...
Kotlin重构Android项目实践
以下是使用 Kotlin 重构 Android 项目的 5 个常见场景实践,通过对比 Java 实现方式,展示 Kotlin 的简洁性和现代特性: 场景 1:数据类替代 Java POJO Java 传统实现: public class User {private String name;private…...
Vue + Element UI 表单弹窗输入法卡顿问题解决方案
Vue Element UI 表单弹窗输入法卡顿问题解决方案 前言 在使用 Vue 和 Element UI 开发后台管理系统时,经常会遇到 el-dialog 弹出表单对话框的场景。然而,很多开发者可能会遇到一个棘手的问题:当调用 resetFields() 方法重置表单时&#x…...
ubantu安装CUDA
想要通过llama.cpp的方式跑deepseek R1模型。在按照https://huggingface.co/unsloth/DeepSeek-R1-GGUF教程去配环境时报错了。具体如下: (base) oemcore:~/Desktop/deepseek_llama.cpp$ sudo cmake llama.cpp -B llama.cpp/build -DBUILD_SHARED_LIBSOFF -DGGM…...
Python生活手册-Numpy多维数组构建:从快递分拣到智能家居的数据变形术
一、快递分拣系统(基础构建) 1. 电子面单生成(列表转数组) import numpy as np手工录入的快递单号 纸质单号 [["SF123", "JD456", "EMS789"],["YT012", "ZT345", "YZ6…...
数据库的范围查询
范围查询 B树迭代器 迭代器接口 B树的基本操作包括用于范围查询的查找和迭代。B树的位置由状态化的迭代器 BIter 表示。 // 查找小于或等于输入键的最近位置 func (tree *BTree) SeekLE(key []byte) *BIter// 获取当前键值对 func (iter *BIter) Deref() ([]byte, []byte)/…...
JS DAY4 日期对象与节点
一日期对象 日期对象:用来表示时间的对象 作用:可以得到当前系统时间 1.实例化 在代码中发现了 new 关键字时,一般将这个操作称为实例化 创建一个时间对象并获取时间 时间必须实例化 获得当前时间 const date new Date() 获得指定时间 const date new Date(…...
【Leetcode 每日一题 - 补卡】1007. 行相等的最少多米诺旋转
问题背景 在一排多米诺骨牌中, t o p s [ i ] tops[i] tops[i] 和 b o t t o m s [ i ] bottoms[i] bottoms[i] 分别代表第 i i i 个多米诺骨牌的上半部分和下半部分。(一个多米诺是两个从 1 1 1 到 6 6 6 的数字同列平铺形成的 —— 该平铺的每一半…...
Android设备运行yolov8
放假这几天搞了一个基于uniapprk3588实现了一版yolo检测 这个是基于前端调用后端api来实现,感觉还可以,但是需要有网络才能进行图像检测,网络不稳定就会出现等待时间会比较久的问题,然后有做了一个在做了一个Android版本的图像检…...
Debezium MySqlValueConverters详解
Debezium MySqlValueConverters详解 1. 类的作用与功能 1.1 核心作用 MySqlValueConverters是Debezium中负责MySQL数据类型转换的核心类,主要功能包括: 数据类型映射:将MySQL的数据类型映射到Kafka Connect的Schema类型值转换:将MySQL的原始值转换为Kafka Connect可用的…...
Redis从入门到实战——实战篇(下)
四、达人探店 1. 发布探店笔记 探店笔记类似于点评网站的评价,往往是图文结合。对应的表有两个: tb_blog:探店笔记表,包含笔记中的标题、文字、图片等tb_blog_comments:其他用户对探店笔记的评价 步骤①࿱…...
算法中的数学:质数(素数)
1.质数 1.1定义 一个大于1的自然数,除了1和它自身外,不能被其他自然数整除,那么他就是质数,否则他就是合数。 注意:1既不是质数也不是合数 唯一的偶质数是2,其余所有质数都是奇质数 1.2质数判定求法 试除法…...
linux、window安装部署nacos
本文以nacos 2.2.0为例 文章目录 1.下载安装包2.按需修改配置配置单机模式配置内存 -Xms -Xmx -Xmn配置数据库为MySQL 3. 访问http://ip:8848/nacos4.常见问题找不到javac命令 1.下载安装包 打开官网,下载2.2.0版本 2.按需修改配置 配置单机模式 默认集群模式&…...
C++ 外观模式详解
外观模式(Facade Pattern)是一种结构型设计模式,它为复杂的子系统提供一个简化的接口。 概念解析 外观模式的核心思想是: 简化接口:为复杂的子系统提供一个更简单、更统一的接口 降低耦合:减少客户端与子…...
42. 接雨水(相向双指针/前后缀分解),一篇文章讲透彻
给定一个数组,代表柱子的高度 求出下雨之后,能接的水有多少单位。我们将每一个柱子想象成一个水桶,看他能接多少水 以这个水桶为例,他所能接的水取决于左边的柱子的最大高度和右边柱子的最大高度,因为只有柱子高的时候…...
vue实现AI问答Markdown打字机效果
上线效果 功能清单 AI问答,文字输出跟随打字机效果格式化回答内容(markdown格式)停止回答,复制回答内容回答时自动向下滚动全屏切换历史问答查看 主要技术 vue 2.7.1markdown-it 14.1.0microsoft/fetch-event-source 2.0.1high…...
【QT】QT中的事件
QT中的事件 1.事件的定义和作用2.QT中事件产生和派发流程2.1 步骤2.2 图示示例代码:(event函数接收所有事件) 3.常见的事件3.1 鼠标事件示例代码:现象: 3.2 按键事件3.3 窗口大小改变事件 4.举例说明示例代码ÿ…...
【QT】QT中的软键盘设计
QT的软键盘设计 1.软键盘制作步骤2.介绍有关函数的使用3.出现的编译错误及解决办法示例代码1:按键事件实现软键盘现象:示例代码2:按键事件实现软键盘(加特殊按键)现象: 软键盘移植到新的工程的步骤…...
【Unity】一个AssetBundle热更新的使用小例子
1.新建两个预制体: Cube1:GameObject Material1:Material Cube1使用了Material1材质 之后设置打包配置 Cube1的打包配置为custom.ab Material1的打包配置为mat.ab 2.在Asset文件夹下创建Editor文件夹,并在Editor下创建BuildBundle…...
【Bootstrap V4系列】学习入门教程之 组件-按钮组(Button group)
Bootstrap V4系列 学习入门教程之 组件-按钮组(Button group) 按钮组(Button group)一、Basic example二、Button toolbar 按钮工具条三、Sizing 尺寸四、Nesting 嵌套五、Vertical variation 垂直变化 按钮组(Button …...
Linux进程间的通信
IPC 即 Inter-Process Communication,也就是进程间通信,它指的是在不同进程之间进行数据交换和协调同步的机制。在操作系统里,每个进程都有自己独立的内存空间,一般情况下不能直接访问其他进程的内存,所以需要借助 IPC…...
常用非对称加密算法的Python实现及详解
非对称加密算法(Asymmetric Encryption)使用公钥加密、私钥解密,解决了对称加密的密钥分发问题。本文将详细介绍 RSA、ECC、ElGamal、DSA、ECDSA、Ed25519 等非对称加密算法的原理,并提供Python实现代码及安全性分析。 1. 非对称加…...
【题解-洛谷】B4303 [蓝桥杯青少年组省赛 2024] 字母移位
题目:B4303 [蓝桥杯青少年组省赛 2024] 字母移位 题目描述 字母移位表示将字母按照字母表的顺序进行移动。 例如, b \texttt{b} b 向右移动一位是 c \texttt{c} c, f \texttt{f} f 向左移动两位是 d \texttt{d} d。 特别地,…...
详讲viewer查看器
将Python与Cesium结合起来,可以实现高效的数据处理与可视化展示。本文将详细介绍如何在Python环境中集成Cesium,以及实现数据可视化的具体方法。 我们可以通过在app.vue中的修改来更改我们查看器的显示方法 修改前 修改后 还可以进行各式各样的自定义操作…...
开关电源原理
开关电源原理 一、 开关电源的电路组成: 开关电源的主要电路是由输入电磁干扰滤波器(EMI)、整流滤波电路、功率变换电路、PWM控制器电路、输出整流滤波电路组成。辅助电路有输入过欠压保护电路、输出过欠压保护电路、输出过流保护电路、输出短…...
数据库的并发控制
并发控制 12.1 并发级别 问题:交错的读写 并发客户端可以随意进入和退出事务,并在中途请求读取和写入。为了简化分析,假设enter/exit/read/write是原子步骤,因此并发事务只是这些步骤的交错。 我们还将区分只读事务和读写事务…...
力扣第448场周赛
赛时成绩如下: 这应该是我力扣周赛的最好成绩了(虽然还是三题) 1. 两个数字的最大乘积 给定一个正整数 n。 返回 任意两位数字 相乘所得的 最大 乘积。 注意:如果某个数字在 n 中出现多次,你可以多次使用该数字。 示例 1: 输入࿱…...
关于Python:9. 深入理解Python运行机制
一、Python内存管理(引用计数、垃圾回收) Python(CPython)采用的是: “引用计数为主,垃圾回收为辅” 的内存管理机制。 也就是说: 引用计数机制:负责大部分内存释放,简…...
Cron表达式的用法
最近几天开发东西用到了定时脚本的问题,中间隔了一段时间没有用到,再次复习一下Cron表达式的用法。 Cron表达式是一种用于定义定时任务执行时间的字符串格式,广泛应用于Unix/Linux系统以及各种编程语言中。其主要用途是通过灵活的时间规则来…...
手机通过局域网访问网狐接口及管理后台网站
1.本地部署接口及后台网站 2.设置允许网站端口通过防火墙 3.查看网站服务器IP 4.手机连接到本地服务器同一局域网 5.手机访问本地服务器接口...