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

【数据结构】(6) LinkedList 链表

一、什么是链表

1、链表与顺序表对比

不同点LinkedListArrayList
物理存储上不连续连续
随机访问效率O(N)O(1)
插入、删除效率O(1)O(N)

3、链表的分类

        链表根据结构分类,可分为单向/双向无头结点/有头节点非循环/循环链表,这三组每组各取一个就构成一种结构链表。其中,单向、不带头、非循环链表学习的重点双向、不带头、非循环链表在实际开发中常用。

        以单向、不带头、非循环链表为例:

        双向、不带头、非循环链表:

        单向、带头、非循环链表(好处在于,不用特别处理头节点,比如增删时):

        单向、不带头、循环链表:

二、单向、不带头、非循环链表的实现

1、IList 接口

        定义 IList 接口,声明线性表需要实现的方法:

package listinterface;public interface IList {//头插法void addFirst(int data);//尾插法void addLast(int data);//任意位置插入,第一个数据节点为0号下标void addIndex(int index,int data);//查找是否包含关键字key是否在单链表当中boolean contains(int key);//删除第一次出现关键字为key的节点void remove(int key);//删除所有值为key的节点void removeAllKey(int key);//得到单链表的长度int size();void clear();void display();
}

2、结点内部类

        结点仅由链表内部使用,且每个结点的产生不依赖于某个链表,可定义为链表的私有静态内部类:

public class MySingleList implements IList {// 结点内部类private static class Node {int data;Node next;public Node(int data) {this.data = data;}}// 头结点private Node head;// 链表长度private int size;............
}

3、打印链表

    @Overridepublic void display() {Node cur = head;while (cur != null) {System.out.print(cur.data + " ");cur = cur.next;}System.out.println(" size: " + size);}

4、清空链表、获取链表长度

    @Overridepublic int size() {return size;}@Overridepublic void clear() {head = null;size = 0;}

        head 为空,没有引用指向 node1,自动回收 node1;node1 回收,没有引用指向 node2,自动回收 node2……故 clear 只需 head 设为 null 即可。

5、头插法

    @Overridepublic void addFirst(int data) {Node newNode = new Node(data);newNode.next = head;head = newNode;
//        if (head != null) {
//            newNode.next = head;
//        }
//        head = newNode;size++;}

6、尾插法

    @Overridepublic void addLast(int data) {Node newNode = new Node(data);if (head == null) {head = newNode;size++;return;}Node cur = head;while (cur.next != null) { // 找到尾节点cur = cur.next;}cur.next = newNode;size++;}

7、任意位置插入

受查异常,父类方法没抛出异常,子类方法不能抛出异常;父类抛出了,子类不做要求。非受查异常,不做要求。)为了不改动 IList,且让 addIndex 抛出异常,以便在 main 处对异常做处理,链表下标越界异常选择继承非受查异常 RuntimeExcption。

package myexception;public class ListIndexOutOfBoundsException extends RuntimeException {public ListIndexOutOfBoundsException(String message) {super(message);}
}
    private void checkIndexOutOfBounds(int index) throws ListIndexOutOfBoundsException {if (index < 0 || index > size) {throw new ListIndexOutOfBoundsException("插入位置不合法。" + "Index: " + index + ", Size: " + size);}}private Node findIndex(int index) {Node cur = head;int cnt = 0;while (cnt != index) {cur = cur.next;cnt++;}return cur;}@Overridepublic void addIndex(int index, int data) throws ListIndexOutOfBoundsException {// 先检查索引是否越界checkIndexOutOfBounds(index);if (index == 0) { // 在 0 处插入,没有前驱节点addFirst(data);return;}if (index == size) { // 在末尾插入addLast(data);return;}Node newNode = new Node(data);// 找到插入位置前的节点Node pre = findIndex(index - 1);// 插入新节点newNode.next = pre.next;pre.next = newNode;size++;}

8、删除第一次出现关键字为key的节点

    private Node findKey(int key) {Node cur = head;while (cur.next != null) {if (cur.next.data == key) {return cur;}cur = cur.next;}return null;}@Overridepublic void remove(int key) {if (head == null) { // 空链表return;}if (head.data == key) { // 头节点就是要删除的节点head = head.next;size--;return;}Node pre = findKey(key);if (pre != null) { // 找到了要删除的节点pre.next = pre.next.next;size--;} else { // 要删除的节点不存在System.out.println("要删除的节点不存在。");}}

9、删除所有关键字为 key 的节点

    @Overridepublic void removeAllKey(int key) {if (head == null) { // 空链表return;}Node pre = head;Node cur = head.next;while (cur != null) {if(cur.data == key) {pre.next = cur.next;// cur = cur.next;}else {pre = cur;// cur = cur.next;}cur = cur.next;}if (head.data == key) {head = head.next;size--;}}

三、链表面试题练习

1、反转链表

206. 反转链表 - 力扣(LeetCode)

思路:从头开始,边遍历边反转,最后尾结点为 head。

class Solution {public ListNode reverseList(ListNode head) {// 特殊处理 空链表、只有一个结点的链表if(head == null || head.next == null) { // 两者顺序不能反,因为 null 没有nextreturn head;}ListNode cur = head.next;// 头结点,其 next 为 null head.next = null;// 边反转边遍历,直到反转完尾结点while(cur != null) {ListNode curN = cur.next; cur.next = head;head = cur;cur = curN;}return head;}
}

2、链表的中间结点

876. 链表的中间结点 - 力扣(LeetCode)

思路

1、计算链表长度的一半,再走一半长。时间复杂度 O(N) + O(N/2)。

2、设置 slow 和 fast 从 head 开始走,slow 每次走 1 步,fast 每次走 2 步。那么 fast 走完全程(fast = null 或者 fast.next = null),必是 slow 的两倍长度,故 slow 就是中间节点的位置。时间复杂度 O(N/2) ,更优。

class Solution {public ListNode middleNode(ListNode head) { // 根据题目,链表非空// 从头节点开始ListNode slow = head;ListNode fast = head;// fast 走完整个链表while(fast != null && fast.next != null) {// slow 每次走 1 步,fast 每次走 2 步slow = slow.next;fast = fast.next.next;}// slow 就是中间结点return slow;}
}

3、返回倒数第 k 个结点

面试题 02.02. 返回倒数第 k 个节点 - 力扣(LeetCode)

思路:slow 从 head 开始,fast 比 slow 先多走 k-1 步,然后 slow、fast 每次只走一步,直到 fast 走到尾结点。

class Solution {public int kthToLast(ListNode head, int k) {// 根据题目,k 保证有效,因此不用判断 k<=0 和 k > len 的情况ListNode slow = head;ListNode fast = head;// 当 fast 先走 k-1 步int cnt = k-1;// k保证有效,fast 不会走过头while(cnt != 0) { fast = fast.next;cnt--;}// 让 fast 走到尾结点,slow 就是倒数第 k 个结点while(fast.next != null) {slow = slow.next;fast = fast.next;}return slow.val;}
}

 4、合并两个有序列表

21. 合并两个有序链表 - 力扣(LeetCode)

思路:分别同时遍历两个链表,更小的插入新链表,插入的链表插入后更新为 next,直到 l1 或者 l2 遍历完了。没遍历完的那个链表,把剩的接在新链表尾。为了不单独处理头指针,新链表带头节点。

class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode head = new ListNode(); // 创建头节点ListNode cur = head;ListNode cur1 = list1;ListNode cur2 = list2;// 其中一个遍历完就退出while(cur1 != null && cur2 != null) {if(cur1.val < cur2.val) {cur.next = cur1;// cur = cur.next;cur1 = cur1.next;}else {cur.next = cur2;// cur = cur.next;cur2 = cur2.next;}cur = cur.next;}// 没遍历完的,接在后面if(cur1 != null) {cur.next = cur1;}if(cur2 != null) {cur.next = cur2;}return head.next; // 不带头节点}
}

5、链表分割

链表分割_牛客题霸_牛客网

思路:先创建两个链表,依次遍历原链表,小于和大于等于 x 的分开尾插入两个链表,再合并。

public class Partition {public ListNode partition(ListNode pHead, int x) {// 创建两个头节点ListNode head1 = new ListNode(-1); ListNode head2 = new ListNode(-1);// 遍历原链表,每个结点与 x 比大小,分类放在两个新链表中ListNode cur1 = head1;ListNode cur2 = head2; while(pHead != null) {if(pHead.val < x) {cur1.next = pHead;cur1 = cur1.next;}else {cur2.next = pHead;cur2 = cur2.next;}pHead = pHead.next;}// 现在 cur1、cur2 分别指向两个链表的尾结点。cur1.next = head2.next; // 链表1的尾接上链表2的头cur2.next = null; // 链表2的尾接上 null// 如果最后链表1为空,cur1就是head1,没问题// 如果最后链表2为空,cur2就是head2,没问题return head1.next;}
}

6、链表的回文结构

链表的回文结构_牛客题霸_牛客网

思路

1、求尾结点,头、尾同时前进并比较,到 head = tail(奇数长度) 或者 head.next = tail (偶数长度)为止。tail 往前走行不通,因为是单链表。

2、把原链表的后一半反转,再将反转链表与原链表对比,直到反转链表遍历完。时间复杂度O(N/2)+O(N/2)+O(N/2)=O(N)。找到一半处、将一半反转、对比一半。

public class PalindromeList {private ListNode findHalf(ListNode head) {ListNode slow = head;ListNode fast = head;while(fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}return slow;}private ListNode reverse(ListNode head) {if(head == null || head.next == null) {return head;}ListNode cur = head.next;head.next = null;while(cur != null) {ListNode curN = cur.next;cur.next = head;head = cur;cur = curN;}return head;}public boolean chkPalindrome(ListNode A) {// 找到中间结点ListNode halfNode = findHalf(A);// 将后一半反转ListNode B = reverse(halfNode);// 将后半段与前半段对比,后半段遍历完退出while(B != null) {if(A.val != B.val) {return false;}A = A.next;B = B.next;}return true;}
}

7、相交链表

160. 相交链表 - 力扣(LeetCode)

思路:可能分叉的地方,前边或后边。但是对于链表不可能后边分叉,因为如果后边分叉了,当你遍历一条单链时,遍历到后边分叉的地方,就不知道继续走哪条路了,这样就不是单链表了。因此只有可能如上图的Y型,或者在一条直线上。

        如果同时各自出发,每次走一步,直到有一方到达尾结点,那么短的链表总是先到达,并且它们的最终距离是两链表的长度差。长度差来自分叉的部分,而不是相交的部分。那么如果让长的先走长度差步,再同时走,它们碰面的地方将是相交处。

public class Solution {private int size(ListNode head) {ListNode cur = head;int cnt = 0;while(cur != null) {cnt++;cur = cur.next;}return cnt;}public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 求两条链的长度int size1 = size(headA);int size2 = size(headB);// 让长的作为 headA,求两链表长度差(正),int len = size1 - size2;if(size1 < size2) {len = size2 - size1;ListNode tmp = headA;headA = headB;headB = tmp;}// 让长的先走 len 步while(len != 0) {headA = headA.next;len--;}// 再同时走,相等的地方就是相交结点while(headA != headB) {headA = headA.next;headB = headB.next;}return headA;}
}

8、环形链表

141. 环形链表 - 力扣(LeetCode)

思路:慢指针和快指针同时走,如果有环,那么快、慢指针总会在环里相遇(快指针多跑 k 圈,然后追上慢指针);如果没环,快指针先走完全程结束。我们设慢指针每次走1步,快指针每次走2步。

        为什么快指针不能是 3、4、……、n 步?如果是3步,存在以下情况,无论走多久都不会相遇:

        快指针如果走 4 步,存在以下情况,无论走多久都不会相遇:

        以此类推……

public class Solution {public boolean hasCycle(ListNode head) {// 设置快、慢指针ListNode slow = head;ListNode fast = head;// slow 每次走1步,fast 每次走2步// 直到 fast = null(偶数个) 或者 fast.next = null(奇数个) 返回 flase// 或者 slow = fast 返回 truewhile(fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;if(slow == fast) {return true;}}return false;}
}

9、环形链表Ⅱ

142. 环形链表 II - 力扣(LeetCode)

思路

        若一指针 head1 从相遇点开始,一指针 head2 从头指针开始,同时走,每次走一步。当 head1 走 X 步到达入口;同时,head2 从相遇点开始走了 (k-1) 圈回到相遇点,再走 N 步到入口。即两指针相遇处,就是入口结点。

public class Solution {private ListNode getMeetNode(ListNode head) {ListNode slow = head;ListNode fast = head;while(fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;if(slow == fast) {return slow;}}return null;}public ListNode detectCycle(ListNode head) {// 获得 slow 与 fast 的相遇结点ListNode meetNode = getMeetNode(head);// 链表无环,返回 nullif(meetNode == null) {return null;}// 分别从头指针,相遇结点开始走,两指针相遇处就是入口while(head != meetNode) {head = head.next;meetNode = meetNode.next;}return head;}
}

四、双向、不带头、非循环链表的实现

1、Node 内部类和属性

public class MyLinkedList  implements IList {private static class Node {int val;Node next; // 后继指针Node prev; // 前驱指针public Node(int val) {this.val = val;}}private Node head; // 头指针private Node tail; // 尾指针private int size; // 链表大小............
}

2、清空链表

        与单向不同直接 head = null,双向需要遍历结点并释放 node,原因如下:head 为空,还有 node2 指向 node1,所以手动置 node2 的 pre 为空,node1释放;还有 node3 指向 node2,手动置 node3 的 pre 未空……

    @Overridepublic void clear() {Node cur = head;while (cur!= null) {Node curN = cur.next;cur.prev = null;cur.next = null;cur = curN;}head = null;tail = null;size = 0;}

3、头插法

    @Overridepublic void addFirst(int data) {Node newNode = new Node(data);if (head == null) {head = newNode;tail = newNode;} else {newNode.next = head;head.prev = newNode;head = newNode;}size++;}

4、尾插法

    @Overridepublic void addLast(int data) {Node newNode = new Node(data);if (head == null) {head = newNode;tail = newNode;} else {tail.next = newNode;newNode.prev = tail;tail = newNode;}size++;}

5、任意位置插入

    @Overridepublic void addIndex(int index, int data) {// 先检查索引是否越界checkIndexOutOfBounds(index);if (index == 0) { // 在 0 处插入,没有前驱节点addFirst(data);return;}if (index == size) { // 在末尾插入addLast(data);return;}Node newNode = new Node(data);// 找到插入位置Node cur = findIndex(index);// 插入新节点newNode.next = cur;newNode.prev = cur.prev;cur.prev.next = newNode;cur.prev = newNode;size++;}

6、删除第一次出现的 key

    private Node findKey(int key) {Node cur = head;while (cur != null) {if (cur.val == key) {return cur;}cur = cur.next;}return null;}@Overridepublic void remove(int key) {Node deleteNode = findKey(key); // 找到待删除节点,如果不存在,返回 nullif (deleteNode == null) { // 包含空链表的情况System.out.println("要删除的节点不存在。");return;}if (deleteNode == head) { // 待删除节点是头节点,包含了链表只有一个结点的情况head = deleteNode.next;if (head == null) { // 链表只有一个节点tail = null;} else {head.prev = null;}} else if (deleteNode == tail) { // 待删除节点是尾节点tail = deleteNode.prev;tail.next = null;} else { // 待删除节点是中间节点deleteNode.prev.next = deleteNode.next;deleteNode.next.prev = deleteNode.prev;}size--;}

7、删除所有 key

    @Overridepublic void removeAllKey(int key) {Node cur = head;while (cur != null) {if (cur.val == key) {if (cur == head) { // 待删除节点是头节点head = cur.next;if (head == null) { // 链表中只有一个节点tail = null;}else {head.prev = null;}} else if (cur == tail) { // 待删除节点是尾节点tail = cur.prev;tail.next = null;} else { // 待删除节点是中间节点cur.prev.next = cur.next;cur.next.prev = cur.prev;}size--;
//                cur = cur.next; // 跳过已删除节点,继续遍历} /*else {cur = cur.next;}*/cur = cur.next;}}

五、LinkedList 的使用

        集合类中,LinkedList 的底层是双向链表

1、常用方法的使用

2、迭代器

        Iterator<E> 是集合类通用的迭代器,线性表专用的迭代器 ListIterator<E> 功能更强,可以反向迭代:

相关文章:

【数据结构】(6) LinkedList 链表

一、什么是链表 1、链表与顺序表对比 不同点LinkedListArrayList物理存储上不连续连续随机访问效率O(N)O(1&#xff09;插入、删除效率O(1)O(N) 3、链表的分类 链表根据结构分类&#xff0c;可分为单向/双向、无头结点/有头节点、非循环/循环链表&#xff0c;这三组每组各取…...

【工具变量】上市公司企业渐进式创新程度及渐进式创新锁定数据(1991-2023年)

测算方式&#xff1a; 参考顶刊《经济研究》孙雅慧&#xff08;2024&#xff09;老师的做法&#xff0c;用当期创新和往期创新的内容重叠度作为衡量渐进式创新程度的合理指标。通过搜集海量专利摘要&#xff0c;测算当前专利申请和既有专利的内容相似度&#xff0c;反映企业在…...

07_任务状态——改进播放控制

一、声明 在05和06的程序里面可以达到的一个效果就是很完美的播放音乐&#xff0c;并且不会影响到其它任务的运行&#xff0c;但是这个代码有一个弊端就是要么创建任务从头开始播放要么就直接删除任务。 我们现在的程序就增加了音乐的暂停和恢复的功能&#xff0c;那么能够达到…...

【R语言】apply函数族

在R语言中使用循环操作时是使用自身来实现的&#xff0c;效率较低。所以R语言有一个符合其统计语言出身的特点&#xff1a;向量化。R语言中的向量化运用了底层的C语言&#xff0c;而C语言的效率比高层的R语言的效率高。 apply函数族主要是为了解决数据向量化运算的问题&#x…...

Retrieval-Augmented Generation,检索增强生成流程

RAG流程 用户输入接收 系统接收用户输入的查询问题或文本内容&#xff0c;例如“李白有哪些著名的作品&#xff1f;”用户输入可以通过自然语言处理&#xff08;NLP&#xff09;模型的输入端口或用户交互界面&#xff08;如聊天应用、搜索引擎输入框等&#xff09;接收。 查询…...

[AI][本地部署]离线升级后报ChromeDb错误

【背景】 升级了OpenWebUI&#xff0c;在离线环境下补足了很多需要的Package后终于成功启动了Backend的服务&#xff0c;但是一旦上传文件&#xff0c;就会报ChromaDb错误&#xff0c;少了Collection这一列云云。 【分析】 两个环境ChromaDb的版本不同&#xff0c;所以怀疑是…...

Pinocchio: 刚体动力学算法库介绍

Pinocchio 是一个高性能的开源刚体动力学计算库&#xff0c;广泛应用于机器人学研究与开发。它主要致力于提供高效、精确的运动学和动力学算法&#xff0c;实现机器人模型的建模、前向运动学、反向动力学、力动力学计算等功能。下面将详细介绍该库的一些关键特点和应用场景。 基…...

电商平台的设计与实现(代码+数据库+LW)

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统商品交易信息管理难度大&#xff0c;容错率低&#xff0…...

c#对接deepseek 聊天AI接口

注意&#xff1a;不是免费 对接文档&#xff1a;对话补全 | DeepSeek API Docs 注册地址&#xff1a;DeepSeek 申请key 在线请求示例 apifox deepseek - deepseek...

Node.js中http模块(二)

一、http模块 http 模块是 Node.js 官方提供的、用来创建 web 服务器的模块。通过 http 模块提供的 http.createServer0) 方法&#xff0c;就能方便的把一台普通的电脑&#xff0c;变成一台 Web 服务器&#xff0c;从而对外提供 Web 资源服务。 二、域名和域名服务器 尽管 I…...

主流顶级域名服务商ZDNS连续十余年跟进国际顶级域名政策制定

顶级域名(TLD,Top-Level Domain)是域名层次结构中的最高层,位于域名最后一段,也即最右边的点(.)之后的字符。品牌顶级域名是顶级域名的一种,以品牌相关名称命名,由品牌所属企业申请、运营、并自由分配二级域名,能够直接反映企业或品牌的形象和特色,如.citic、.中信、.baidu、.联…...

低至3折,百度智能云千帆宣布全面支持DeepSeek-R1/V3调用

DeepSeek-R1和 DeepSeek-V3模型已在百度智能云千帆平台上架 。 出品|产业家 新年伊始&#xff0c;百度智能云又传来新动作 。 2月3日百度智能云宣布&#xff0c; DeepSeek-R1和 DeepSeek-V3模型已在百度智能云千帆平台上架&#xff0c;同步推出超低价格方案&#xff0c;并…...

解释一下数据库中的事务隔离级别,在 Java 中如何通过 JDBC设置事务隔离级别?

数据库中的事务隔离级别是用于控制并发事务之间相互影响的一种机制。 它定义了事务之间的可见性和影响范围&#xff0c;常见的隔离级别包括&#xff1a; 读未提交&#xff08;Read Uncommitted&#xff09;&#xff1a;最低的隔离级别&#xff0c;事务中的修改即使没有提交也…...

【自动化测试】使用Python selenium类库模拟手人工操作网页

使用Python selenium类库模拟手人工操作网页 背景准备工作安装Python版本安装selenium类库下载selenium驱动配置本地环境变量 自动化脚本输出页面表单自动化填充相关代码 背景 待操作网页必须使用IE浏览器登录访问用户本地只有edge浏览器&#xff0c;通过edge浏览器IE模式访问…...

【Apache Paimon】-- 15 -- 利用 paimon-flink-action 同步 postgresql 表数据

利用 Paimon Schema Evolution 核心特性同步变更的 postgresql 表结构和数据 1、背景信息 在Paimon 诞生以前,若 mysql/pg 等数据源的表结构发生变化时,我们有几种处理方式 (1)人工消息通知,然后手动同步到数据仓库中(2)使用 flink 消费 DDL binlog ,然后自动更新 Hi…...

PostgreSql-COALESCE函数、NULLIF函数、NVL函数使用

COALESCE函数 COALESCE函数是返回参数中的第一个非null的值&#xff0c;它要求参数中至少有一个是非null的; select coalesce(1,null,2),coalesce(null,2,1),coalesce(null,null,null); NULLIF(ex1,ex2)函数 如果ex1与ex2相等则返回Null&#xff0c;不相等返回第一个表达式的值…...

springboot+vue导入ruoyi项目的框架

一、介绍 RuoYi-Vue版本&#xff0c;采用了前后端分离的单体架构设计软件环境&#xff1a;JDK、Mysql、Redis、Maven、Node技术选型: Spring Boot、Spring Security、MyBatis、Jwt、Vue3、Element-Plus官方地址: https://gitee.com/y_project/RuoYi-Vue 官方推荐的版本如下&a…...

金蛇祈福,鸿运开年!广州白云皮具城2025开市大吉!

锣鼓一响&#xff0c;黄金万两&#xff01;2月6日大年初九&#xff0c;广州白云皮具城举行盛大的醒狮开市仪式&#xff01;象征吉祥如意的醒狮&#xff0c;将好运、财运传递给全体商户和八方来客。 醒狮点睛 金鼓一响黄金万两&#xff0c;十头醒狮登台&#xff0c;董事总经理刘…...

DeepSeek本地化部署

文章目录 前言一、主机配置二、工具下载Ollama下载安装退出Ollama下载DeepSeek R1模型下载安装ChatBox实现可视化交互ChatBox设置模型 前言 最近的国产大模型DeepSeek横空出事&#xff0c;笔者也关注了下。网页版的免费而且推理速度很快&#xff0c;重量级的是它把自己详细的推…...

MoviePy,利用Python自动剪辑tiktok视频

Python剪辑视频是非常强大的&#xff0c;而且能流水线批量操作&#xff0c;可以使用MoviePy库实现。 最近看到一个Github项目&#xff0c;作者利用Python写了一个自动生成tiktok视频的脚本&#xff0c;受到热捧。 现在像抖音、tiktok上有很多流水线生产的视频&#xff0c;不少…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

ubuntu22.04 安装docker 和docker-compose

首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

Unity VR/MR开发-VR开发与传统3D开发的差异

视频讲解链接&#xff1a;【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...