c# 数据结构 链表篇 有关单链表的一切
本人能力有限,本文仅作学习交流与参考,如有不足还请斧正
目录
0.单链表好处
0.5.单链表分类
1.无虚拟头节点情况
图示:
代码:
头插/尾插
删除
搜索
遍历全部
测试代码:
全部代码
2.有尾指针情况
尾插
全部代码
3.有虚拟头节点情况
全部代码
4.循环单链表
几个特别说明的点
增加时 更新环结构
删除时 删的头节点
非删头节点 注意遍历终止条件
全部代码
0.单链表好处
| 优点 | 说明 / 场景 |
|---|---|
| 动态内存分配 | 节点按需创建,无需预先指定固定大小,避免数组的空间浪费或溢出(如数据量不确定时) |
| 高效增删操作 | 插入 / 删除只需修改指针(平均 O(1) 时间复杂度),尤其适合频繁增删场景(如栈、队列) |
| 内存分散存储 | 节点可存储在非连续内存中,适应碎片化内存,利用零散空间(对比数组需连续内存) |
| 灵活动态长度 | 长度可随时增减,无需扩容 / 缩容(如动态缓冲区、链表队列) |
| 实现简单轻量 | 节点结构简单(数据 + 指针),代码易理解,适合入门学习及快速实现基础数据结构 |
| 适合链式场景 | 支持链表特有操作(反转、合并、判环等),常用于哈希表拉链法、操作系统进程调度等 |
0.5.单链表分类
| 分类维度 | 类型 | 核心特点 | 典型场景 / 优势 |
|---|---|---|---|
| 头节点 | 无头节点 | 头指针直接指向第一个数据节点,需处理头节点边界条件 | 简单场景,代码稍繁琐 |
| 有头节点 | 头节点为虚拟节点,简化插入 / 删除操作 | 通用场景,代码更简洁 | |
| 循环 | 非循环 | 尾节点 next 为 null,遍历有终点 | 大多数基础场景 |
| 循环 | 尾节点 next 指向头节点,形成环 | 循环遍历、约瑟夫环等问题 | |
| 辅助指针 | 无尾指针 | 尾插需遍历链表(\(O(n)\)) | 尾插操作较少的场景 |
| 带尾指针 | 尾插直接通过尾指针操作(\(O(1)\)) | 频繁尾插的场景 |
下无特殊说明 皆为非循环单链表
1.无虚拟头节点情况
请注意 无头节点的意思是没有虚拟头节点
而下所说的headNdoe代表的是实际数据第一个节点
单链表 = 实际数据头节点 + (节点 1 + 节点 2 + … + 节点 n) 其中,每个节点的定义为: 节点 = 数据 + 指向下一个节点的指针
图示:
注意 因为写c#的时候使用指针需要注意下列问题:
所以指向下一个节点的指针 定义为Node类 也就是Node本身

代码:
class Node { public int value;public Node nextNode;public Node(int value, Node nextNode) {this.value = value;this.nextNode = nextNode;}
}
头插/尾插
头插的精髓:每一次插入新node的时候 就把旧headNode作为nextNode,然后改变head的指向即可

class LinkeList {public Node headNode;public LinkeList() {headNode = null;}//头插: 新节点的next指向头节点,然后将头节点指向新节点public void AddToHead(int value) { //创建一个新节点 并把原来的头节点放到后面去 这就是头插法的精髓Node newNode = new Node(value, headNode);//将头节点指向新节点headNode = newNode;}
}
尾插精髓:遍历到最后一个节点 将该节点NextNode指向新Node

public void AddToTail(int value) {//创建一个新节点Node newNode = new Node(value, null);//如果链表为空,则直接将新节点作为头节点if (headNode == null)headNode = newNode;else { //遍历到最后一个节点Node currentNode = headNode;while (currentNode.nextNode != null){ currentNode = currentNode.nextNode; }currentNode.nextNode = newNode;}
}
删除
按值删除:单值
精髓:删除不是让你真删掉,而是将Node的指针置null 这样gc的时候就自动回收了
找到需要删除的节点的上一个节点,将其nextNode = 要删除节点的下一个Node

//按值删除public void RemoveForValue(int value) {//如果链表为空,则直接返回if (headNode == null)return;//如果头节点就是要删除的节点,则直接将头节点指向目标的下一个节点//相当于断开了原来的头节点 使其无用if (headNode.value == value) {headNode =headNode.nextNode;return;}//遍历链表 Node currentNode = headNode;while (currentNode!=null&¤tNode.nextNode != null){if (currentNode.nextNode.value != value)currentNode = currentNode.nextNode;elsecurrentNode.nextNode = currentNode.nextNode.nextNode;}}
按值删除:删除所有匹配到的重复值
public void RemoveForValue(int value){// 1. 处理头节点的所有重复值(用while循环替代if)while (headNode != null && headNode.value == value){headNode = headNode.nextNode; // 连续删除头节点中的重复值}// 2. 遍历删除中间和尾节点的重复值Node currentNode = headNode;while (currentNode != null){// 检查当前节点的下一个节点是否是目标值(避免漏判尾节点)while (currentNode.nextNode != null && currentNode.nextNode.value == value){currentNode.nextNode = currentNode.nextNode.nextNode; // 删除下一个节点(重复值)}currentNode = currentNode.nextNode; // 移动到下一个非重复值节点}}
按节点删除 略
这个你知道有这么回事就行了 一般不会用到 因为他在使用的时候需要声明要删除的Node 所以从用户角度来看就不太友好 不建议使用
搜索
按值遍历
精髓:没有精髓 遍历按值打印即可
public bool SerachValue(int value){if (headNode == null) { Console.WriteLine("链表为空 无法找到指定值"); return false; }Node currentNode = headNode;while (currentNode != null&& currentNode.nextNode != null){if (currentNode.value == value){Console.WriteLine("包含指定值" + value);return true;}else {currentNode = currentNode.nextNode;}}Console.WriteLine("链表内没有指定值" + value);return false;}
遍历全部
精髓:没有精髓 遍历按值打印即可
public void PrintAllValue() {if (headNode == null) return;Node currentNode = headNode;while (currentNode!= null){Console.WriteLine(currentNode.value);currentNode = currentNode.nextNode;}}
测试代码:
LinkeList linke = new LinkeList();
linke.AddToHead(2);
linke.AddToHead(1);
linke.AddToTail(3);
//1 2 3
linke.RemoveForValue(2);
//1 3
Console.WriteLine(linke.SerachValue(2));//false
Console.WriteLine(linke.SerachValue(1));//truelinke.PrintAllValue(); // 1 3

全部代码
using System.Buffers;LinkeList linke = new LinkeList();
linke.AddToHead(2);
linke.AddToHead(1);
linke.AddToTail(3);
//1 2 3
linke.RemoveForValue(2);
//1 3
Console.WriteLine(linke.SerachValue(2));//false
Console.WriteLine(linke.SerachValue(1));//truelinke.PrintAllValue(); // 1 3/// <summary>
/// 链表节点应该包含 值 和 指针
/// </summary>
class Node { public int value;public Node nextNode;public Node(int value, Node newNode) {this.value = value;this.nextNode = newNode;}
}
class LinkeList {public Node headNode;public LinkeList() {headNode = null;}#region Add//头插: 新节点的next指向头节点,然后将头节点指向新节点public void AddToHead(int value){//创建一个新节点 并把原来的头节点放到后面去 这就是头插法的精髓Node newNode = new Node(value, headNode);//将头节点指向新节点headNode = newNode;}//尾插public void AddToTail(int value){//创建一个新节点Node newNode = new Node(value, null);//如果链表为空,则直接将新节点作为头节点if (headNode == null)headNode = newNode;else{//遍历到最后一个节点Node currentNode = headNode;while (currentNode.nextNode != null){ currentNode = currentNode.nextNode; }currentNode.nextNode = newNode;}}#endregion#region Remove//按值删除public void RemoveForValue(int value) {//如果链表为空,则直接返回if (headNode == null)return;//如果头节点就是要删除的节点,则直接将头节点指向目标的下一个节点//相当于断开了原来的头节点 使其无用if (headNode.value == value) {headNode =headNode.nextNode;return;}//遍历链表 Node currentNode = headNode;while (currentNode!=null&¤tNode.nextNode != null){if (currentNode.nextNode.value != value)currentNode = currentNode.nextNode;elsecurrentNode.nextNode = currentNode.nextNode.nextNode;}}#endregion#region Searchpublic bool SerachValue(int value){if (headNode == null) { Console.WriteLine("链表为空 无法找到指定值"); return false; }Node currentNode = headNode;while (currentNode != null&& currentNode.nextNode != null){if (currentNode.value == value){Console.WriteLine("包含指定值" + value);return true;}else {currentNode = currentNode.nextNode;}}Console.WriteLine("链表内没有指定值" + value);return false;}#endregion#region 遍历打印public void PrintAllValue() {if (headNode == null) return;Node currentNode = headNode;while (currentNode!= null){Console.WriteLine(currentNode.value);currentNode = currentNode.nextNode;}}#endregion
}
2.有尾指针情况
这个的特别之处在于尾巴辅助的话 尾插不用遍历到最后尾巴
初始化的时候需要注意一下
尾插
class LinkeList
{public Node headNode;public Node tailNode;public LinkeList(){headNode = tailNode = null;}
}
// 尾插public void AddToTail(int value){Node newNode = new Node(value);if (headNode == null)headNode = tailNode = newNode;tailNode.nextNode = newNode;tailNode = newNode;}
其他的就没什么了和无虚拟头节点的代码和方法几乎是一样的
全部代码
using System.Diagnostics;LinkeList linkeList = new LinkeList();
linkeList.AddToHead(2);
linkeList.AddToHead(1);
linkeList.AddToTail(3);
linkeList.RemoveForValue(3);
linkeList.SerachValue(2);
linkeList.SerachValue(3);
linkeList.PrintAllValue();
class Node
{public int value;public Node nextNode;public Node(int value, Node newNode = null){this.value = value;this.nextNode = newNode;}
}class LinkeList
{public Node headNode;public Node tailNode;public LinkeList(){headNode = tailNode = null;}#region Add// 头插public void AddToHead(int value){Node newNode = new Node(value,headNode);if (headNode == null) headNode = tailNode = newNode;headNode = newNode;}// 尾插public void AddToTail(int value){Node newNode = new Node(value);if (headNode == null)headNode = tailNode = newNode;if(tailNode!= null)tailNode.nextNode = newNode;elsetailNode = newNode;}#endregion#region Remove// 按值删除:双向查找 删除第一个找到的值public void RemoveForValue(int value){//头空 直接返回if (headNode == null)return;//只有一个头if (headNode.value == value){if (headNode.nextNode == null)headNode = tailNode = null;return;}Node currentNode = headNode;while (currentNode!=null && currentNode.nextNode != null){//如果下一个节点的值等于要删除的值if (currentNode.nextNode.value == value) {//在尾巴上 就更新尾巴if (currentNode.nextNode == tailNode){tailNode = currentNode;}//不在尾巴上 就干掉下一个节点currentNode.nextNode = currentNode.nextNode.nextNode;}elsecurrentNode = currentNode.nextNode;}}#endregion#region Searchpublic bool SerachValue(int value){if (headNode == null)return false;Node currentNode = headNode;while (currentNode != null && currentNode.nextNode != null){//如果下一个节点的值等于要删除的值if (currentNode.nextNode.value == value){Console.WriteLine("找到了目标值"+value);return true;}elsecurrentNode = currentNode.nextNode;}Console.WriteLine("没找到了目标值" + value);return false; }#endregion#region 遍历打印public void PrintAllValue(){Node currentNode = headNode;while (currentNode != null){Console.WriteLine(currentNode.value);currentNode = currentNode.nextNode;}}#endregion
}
3.有虚拟头节点情况
我认为其没有什么特别的含义 只是省去了头节点为null的判断 我截图对比一下
左无头 右有头


全部代码
using System;
LinkeList linke = new LinkeList();
linke.AddToHead(2);
linke.AddToHead(1);
linke.AddToTail(3);
// 1 2 3
linke.RemoveForValue(2);
// 1 3
Console.WriteLine(linke.SerachValue(2));// false
Console.WriteLine(linke.SerachValue(1));// truelinke.PrintAllValue(); // 1 3
/// <summary>
/// 链表节点应该包含 值 和 指针
/// </summary>
class Node
{public int value;public Node nextNode;public Node(int value, Node newNode = null){this.value = value;this.nextNode = newNode;}
}class LinkeList
{// 虚拟头节点private Node dummyHead;public LinkeList(){// 初始化虚拟头节点dummyHead = new Node(0);}#region Add// 头插: 新节点的next指向虚拟头节点的下一个节点,然后将虚拟头节点的next指向新节点public void AddToHead(int value){Node newNode = new Node(value, dummyHead.nextNode);dummyHead.nextNode = newNode;}// 尾插public void AddToTail(int value){Node newNode = new Node(value);Node currentNode = dummyHead;while (currentNode.nextNode != null){currentNode = currentNode.nextNode;}currentNode.nextNode = newNode;}#endregion#region Remove// 按值删除public void RemoveForValue(int value){Node currentNode = dummyHead;while (currentNode != null && currentNode.nextNode != null){if (currentNode.nextNode.value == value){currentNode.nextNode = currentNode.nextNode.nextNode;}else{currentNode = currentNode.nextNode;}}}#endregion#region Searchpublic bool SerachValue(int value){Node currentNode = dummyHead.nextNode;while (currentNode != null){if (currentNode.value == value){Console.WriteLine("包含指定值" + value);return true;}currentNode = currentNode.nextNode;}Console.WriteLine("链表内没有指定值" + value);return false;}#endregion#region 遍历打印public void PrintAllValue(){Node currentNode = dummyHead.nextNode;while (currentNode != null){Console.WriteLine(currentNode.value);currentNode = currentNode.nextNode;}}#endregion
}
4.循环单链表
我直接用情况2 的代码改的 核心在于:
- 尾节点的
nextNode指向头节点(形成环) - 遍历 / 搜索时通过头节点判断终止条件(避免死循环)
- 维护头尾指针的环结构一致性
你要是问都循环了 还区分头尾节点有必要吗?
有的兄弟,有的 这样头尾插都是O1
几个特别说明的点
增加时 更新环结构

// 尾插法:新节点的next指向头节点,原尾节点的next指向新节点,更新尾节点public void AddToTail(int value){Node newNode = new Node(value, headNode); // 新节点的next指向头节点(形成环)if (tailNode == null){// 空链表:头尾节点指向新节点,自环headNode = tailNode = newNode;newNode.nextNode = newNode;}else{tailNode.nextNode = newNode; // 原尾节点连接新节点tailNode = newNode; // 尾节点更新为新节点}}
删除时 删的头节点
public void RemoveForValue(int value){if (headNode == null) return;// 情况1:删除头节点if (headNode.value == value){if (headNode == tailNode) // 只有一个节点{headNode = tailNode = null; // 环断开}else // 多个节点,头节点后移,尾节点的next指向新头节点{headNode = headNode.nextNode;tailNode.nextNode = headNode; // 尾节点保持环结构}return;}.................}
非删头节点 注意遍历终止条件

while (previous.nextNode != headNode){if (previous.nextNode.value == value){Node target = previous.nextNode;if (target == tailNode){tailNode = previous;tailNode.nextNode = headNode;}else{previous.nextNode = target.nextNode;}}else{previous = previous.nextNode;}}
全部代码
class Node
{public int value;public Node nextNode;public Node(int value, Node nextNode = null){this.value = value;this.nextNode = nextNode;}
}class CircularLinkedList
{public Node headNode;public Node tailNode;public CircularLinkedList(){headNode = tailNode = null;}// 头插法public void AddToHead(int value){Node newNode = new Node(value, headNode);if (headNode == null){headNode = tailNode = newNode;newNode.nextNode = newNode;}else{tailNode.nextNode = newNode;headNode = newNode;}}// 按值删除节点public void RemoveForValue(int value){if (headNode == null) return;// 处理头节点是要删除的值的情况while (headNode != null && headNode.value == value){if (headNode == tailNode){headNode = tailNode = null;return;}headNode = headNode.nextNode;tailNode.nextNode = headNode;}Node previous = headNode;while (previous.nextNode != headNode){if (previous.nextNode.value == value){Node target = previous.nextNode;if (target == tailNode){tailNode = previous;tailNode.nextNode = headNode;}else{previous.nextNode = target.nextNode;}}else{previous = previous.nextNode;}}}// 遍历打印链表public void PrintAllValue(){if (headNode == null) return;Node current = headNode;do{Console.WriteLine(current.value);current = current.nextNode;} while (current != headNode);}
}
相关文章:
c# 数据结构 链表篇 有关单链表的一切
本人能力有限,本文仅作学习交流与参考,如有不足还请斧正 目录 0.单链表好处 0.5.单链表分类 1.无虚拟头节点情况 图示: 代码: 头插/尾插 删除 搜索 遍历全部 测试代码: 全部代码 2.有尾指针情况 尾插 全部代码 3.有虚拟头节点情况 全部代码 4.循环单链表 几个…...
VS Code连接服务器编写Python文件
1、下载 Visual Studio Code 2、打开扩展(ctrl shift x ) 3、搜索 Remote - SSH,安装 4、F1 或者 点金左下角 5、选择:Remote-SSH: Connect to Host……,回车 6、第一次用的时候,VS Code 会提示添加 SSH 主机。输…...
图解AUTOSAR_SWS_FlexRayNetworkManagement
FlexRay网络管理详解 AUTOSAR标准FlexRay网络管理模块技术说明 目录 1. FlexRay网络管理概述 1.1 模块功能与目的1.2 适用范围与限制2. FlexRay网络管理架构 2.1 模块层次结构2.2 组件交互关系3. FlexRay网络管理状态机 3.1 状态转换机制3.2 主要状态说明4. FlexRay网络管理通信…...
Gitea的安装和配置以及应用
Gitea的安装和配置以及应用 一、安装 1、创建数据库和数据库账户(pg) su – postgres -c "psql" CREATE ROLE gitea WITH LOGIN PASSWORD gitea; CREATE DATABASE giteadb WITH OWNER gitea TEMPLATE template0 ENCODING UTF8 LC_COLLATE …...
Blender 转 STL 文件全攻略:从基础到进阶
在 3D 建模与打印领域,Blender 凭借其强大的功能和开源特性,深受创作者喜爱。而 STL 文件格式,作为 3D 打印行业的通用标准,能被绝大多数 3D 打印软件和设备所识别。因此,将 Blender 模型转换为 STL 文件,是…...
UI自动化基础(1)
1、pip install selenium4.3.0,最好指定版本安装,因为不同的版本可能会有一些兼容 性的问题。 2、pip uninstall urllib3 ,pip install urllib31.26.15 【执行版本安装】,goole是114.版本 3、装好浏览器,正确安装。最好…...
$_GET变量
$_GET 是一个超级全局变量,在 PHP 中用于收集通过 URL 查询字符串传递的参数。它是一个关联数组,包含了所有通过 HTTP GET 方法发送到当前脚本的变量。 预定义的 $_GET 变量用于收集来自 method"get" 的表单中的值。 从带有 GET 方法的表单发…...
TBE(TVM的扩展)
算子 张量 一个张量只有一种数据类型 在内存中只能线性存储,最终形成一个长的一维数组 晟腾AI的数据格式 AIPP是对我们常见的数据格式转化成AI core支持的数据格式 广播机制 TVM TBE的第一种开发方式:DSL TBE的第二种开发方式:TVM TBE的第…...
【Function Calling与Tool Calling】深度解析大模型智能中枢的架构革命
目录 一、范式转移:从对话引擎到智能中枢 二、核心技术解析 2.1 Function Calling技术栈 2.2 Tool Calling实现模式 三、企业级应用架构设计 3.1 智能工单系统案例 3.2 性能优化策略 四、安全与治理框架 4.1 权限控制矩阵 4.2 审计追踪设计 五、开发者实…...
知识表示方法之六:过程表示法(Procedural Representation)
在人工智能的发展史中,关于知识的表示方法曾存在两种不同的观点。一种观点认为知识主要是陈述性的,其表示方法应着重将其静态特性,即事物的属性以及事物间的关系表示出来,称以这种观点表示知识的方法为陈述式或说明式表示法&#…...
Java 中序列化和反序列化
Java 中的序列化(Serialization)和反序列化(Deserialization)是将对象和二进制数据(或其他格式)之间转换的过程,常见于对象传输、缓存、持久化等场景。 下面是 Java 中常见的几种 序列化/反序列…...
sql-labs靶场 less-2
文章目录 sqli-labs靶场less 2 联合注入 sqli-labs靶场 每道题都从以下模板讲解,并且每个步骤都有图片,清晰明了,便于复盘。 sql注入的基本步骤 注入点注入类型 字符型:判断闭合方式 (‘、"、’、“”…...
Spring配置部分
Spring配置部分 单纯的使用Spring可以通过配置文件xml,配置注解,全注解方式执行 无论使用哪种方式,都需要在Main方法中加载配置(配置文件或者注解)获取到Spring容器,在通过容器的GetBean方法获取Bean对象…...
git clone(复制)下载
1、复制 下载地址 2、打开网页,点击 克隆/下载按扭 3、按提示复制命令行到终端 4、VS里打开终端,并粘贴以下命令 5、 下载完毕 6、复制文件夹到你选定的位置 7、用VSCODE打开文件夹,开始你接下来的工作...
Android设置adjustResize时无法生效 解决办法
删除Activity类下执行全屏的一行参数。 将图中这段Activity类中执行命令给删除就解决了。 注意关闭后状态栏和导航栏的透明度就无法自动处理了,需要到values和values-night下的themes.xml手动设置状态栏背景颜色。 <item name"android:statusBarColor"…...
按键长按代码
这些代码都存放在定时器中断中。中断为100ms中断一次。 数据判断,看的懂就看吧...
Idea将Java工程打包成war包并发布
1、问题概述? 项目开发之后,我们需要将Java工程打包成war后缀,并进行发布。之前在网上看到很多的文章,但是都不齐全,今天将提供一个完整的实现打包war工程,并发布的文章,希望对大家有所帮助,主要解决如下问题: 1、war工程需要满足的相关配置 2、如何解决项目中的JDK…...
SGLang实战问题全解析:从分布式部署到性能调优的深度指南
引言:当高性能推理遇上复杂生产环境 在大型语言模型(LLM)的生产部署中,SGLang以其革命性的RadixAttention和结构化编程能力,正成为越来越多企业的首选推理引擎。然而,当我们将32B/70B级别的大模型部署到实际生产环境时࿰…...
优选算法第八讲:链表
优选算法第八讲:链表 1.链表常用操作和技巧总结2.两数相加3.两两交换链表中的节点4.重排链表5.合并k个升序链表6.k个一组翻转链表 1.链表常用操作和技巧总结 2.两数相加 3.两两交换链表中的节点 4.重排链表 5.合并k个升序链表 6.k个一组翻转链表...
Python语言的需求分析
Python语言的需求分析 引言 在信息技术快速发展的今天,编程语言的选择对于软件开发的成功与否起着至关重要的作用。Python作为一种高级编程语言,以其简洁易读的语法和强大的功能受到越来越多开发者的青睐。通过对Python语言的需求分析,我们…...
vue项目本地调试使用https
由于测试环境远程接口,是采用https协议,为了能正常携带cookie访问接口,需要把本地项目也采用https协议访问。前提是后端的cookie设置在二级域名下,且允许固定其他子域名跨域访问(需要在后端设置) 项目框架…...
4S店汽车维修保养管理系统 (源码+lw+部署文档+讲解),源码可白嫖!
摘要 二十一世纪我们的社会进入了信息时代,信息管理系统的建立,大大提高了人们信息化水平。传统的管理方式已经与当今4S店汽车维修保养管理系统的业务需求不相适应,也与4S店汽车维修保养管理系统化建设的发展趋势不相适应。本文针对这一需求设计并实现了…...
【NLP 面经 8】
目录 一、文本生成任务 模型架构方面 训练数据方面 生成策略方面 二、命名实体识别任务NER 模型架构方面 特征工程方面 训练优化方面 三、情感分析任务 模型架构方面 训练数据方面 超参数调整方面 四、计算余弦相似度并添加符合条件结果 提示: 思路与算法 任由深渊的…...
UE5学习笔记 FPS游戏制作43 UI材质
文章目录 实现目标制作UI材质使用UI材质 实现目标 把图片变为灰色 制作UI材质 右键新建一个材质 左侧细节栏,材质域改为用户界面,混合模式改为半透明 此时输出节点应该有两个属性 在内容浏览器里找到要用的图片,然后向上拖动到材质标题…...
12、主频和时钟配置实验
一、I.MX6U 时钟系统详解 1、系统时钟来源 开发板的系统时钟来源于两部分: 32.768KHz 和24MHz 的晶振,其中 32.768KHz 晶振是 I.MX6U 的 RTC 时钟源, 24MHz 晶振是 I.MX6U 内核和其它外设的时钟源。 2、7路PLL时钟源 I.MX6U 的外设有很多,不同的外设时钟源不同, NXP 将…...
网络安全小知识课堂(十一)
数据加密:明文传输为什么极度危险? 引言 当你在咖啡店连上公共 WiFi,悠闲地浏览网页时,是否想过黑客可能正在 “偷看” 你的一举一动?如果网站未启用加密,你输入的账号密码、聊天记录,甚至支付…...
Redis 与 MongoDB 对比分析
Redis 与 MongoDB 对比分析 1. 核心定位 Redis:内存键值数据库,侧重高性能读写和低延迟,常用于缓存、实时分析、消息队列等场景。MongoDB:分布式文档型数据库,侧重灵活的数据模型和大规模数据存储,支持复…...
2025 年河北交安安全员考试:巧用行业报告丰富知识储备
河北交通行业发展迅速,各类行业报告蕴含大量有价值信息。考生可从河北省交通运输行业发展报告、安全专项检查报告等资料入手。在行业发展报告中,了解本省交通建设规模、重点项目规划等内容,这些信息与交安安全员工作紧密相关。比如࿰…...
2025快递业绿色包装创新发展论坛(上海)将于9月3日举办
2025快递业绿色包装创新发展论坛(上海)将于9月3日举办 为进一步推进快递包装标准化、循环化、减量化、无害化转型,促进邮政快递业绿色低碳发展,在“2025 快递物流新质生产力发展论坛暨 2025 长三角国际快递物流供应链与智能装备…...
QML面试笔记--UI设计篇06信息展示控件
1. QML常用信息展示控件详解:打造优雅用户界面的秘密武器 1.1. Text:界面信息的基础载体1.2. Image:视觉信息的魔法师1.3. ListView:数据洪流的指挥官1.4. Repeater:布局魔术师1.5. 创新用法: 2. 界面设计…...
