list的模拟实现

  • 一.list与vector
      • 1.底层结构的本质区别
      • 2.模拟实现的核心差异
        • 2.1数据存储的方式
        • 2.2 初始化的过程
        • 2.3 插入元素的操作
        • 2.4 删除元素的操作
        • 2.5 访问元素的效率
      • 3.总结
  • 二.头文件list.h
      • 1. **命名空间与模板**
      • 2. **核心数据结构**
      • 3. **构造函数**
      • 4. **模板参数设计**
      • 5. **核心成员**
      • 6. **构造与析构**
      • 7. **操作符重载**
      • 8. **类型定义**
      • 9. **迭代器接口**
      • 10. **内存管理**
      • 11. **构造函数**
      • 12. **初始化列表构造函数**
      • 13. **交换方法**
      • 14. **赋值运算符重载**
      • 15. **链表初始化**
      • 16. **清空操作**
      • 17. **首尾操作**
      • 18. **插入操作**
      • 19. **删除操作**
  • 三.头文件test.cpp
      • 1. **打印函数**
      • 2. **测试函数1**
      • 3. **测试函数3:迭代器操作测试**
      • 4. **测试函数4:插入删除测试**

一.list与vector

顺序表与链表因底层结构不同而导致的模拟实现差异。

1.底层结构的本质区别

  • 顺序表:像一排连续的“格子”,所有元素按顺序依次放进这些格子里,每个格子紧挨着下一个,中间没有空隙。整个结构占用一整块连续的内存空间,元素的位置(比如第1个、第2个)和它们在内存中的物理位置完全对应。
  • 链表:像一串“珠子”,每个珠子(称为“节点”)分为两部分:一部分装数据,另一部分装一个“指向”下一个珠子的“钩子”(指针或引用)。这些珠子在内存中可能分散在不同位置,全靠钩子串联起来形成逻辑上的顺序,物理位置和逻辑位置无关。

2.模拟实现的核心差异

基于上述底层结构,两者的实现逻辑(比如怎么存数据、怎么加元素、怎么删元素)完全不同:

2.1数据存储的方式
  • 顺序表
    实现时需要先划定一块固定大小的连续空间(比如先准备10个格子),用一个“容器”管理这些格子,同时记录当前装了多少元素(比如已用3个格子)和总共能装多少(10个)。元素的位置可以直接算出来:第i个元素一定在第1个元素往后数i个格子的位置,所以能直接找到。

  • 链表
    实现时不需要预先划定空间,而是用一个“头指针”记录第一个节点的位置,每个节点都是单独创建的(需要时才申请内存)。每个节点除了数据,必须带一个“钩子”指向后面的节点,最后一个节点的钩子指向“空”,表示结束。元素的位置无法直接算,只能从第一个节点开始,顺着钩子一个个找。

2.2 初始化的过程
  • 顺序表
    核心是“圈定初始空间”。比如一开始决定能装5个元素,就申请一块能放下5个元素的连续内存,然后标记“当前装了0个元素”。如果后续元素超过5个,就需要“扩容”——重新申请一块更大的连续内存(比如能装10个),把原来的元素搬过去,再用新空间替代旧空间。

  • 链表
    核心是“确定起点”。通常初始化时,要么让头指针指向“空”(表示链表为空),要么先创建一个“哨兵节点”(不存数据,专门用来统一操作),头指针指向这个哨兵节点,同时标记“当前有0个元素”。后续添加元素时,再一个个创建新节点,用钩子连起来即可,不需要提前规划总容量。

2.3 插入元素的操作
  • 顺序表
    如果要在第i个位置插入元素,必须先检查当前空间是否够用(不够就扩容),然后把第i个及之后的所有元素都往后“挪一个位置”(腾出第i个格子),最后把新元素放进第i个格子,再更新“已用元素数”。
    比如在“[1,2,3]”的第2个位置插4,需要先把2、3往后挪,变成“[1, ,2,3]”,再放4,结果是“[1,4,2,3]”。

  • 链表
    如果要在第i个位置插入元素,不需要挪动其他元素,只需要:

    1. 新建一个节点,存入数据;
    2. 找到第i-1个节点,把它的钩子从原来指向第i个节点,改成指向新节点;
    3. 再让新节点的钩子指向原来的第i个节点。
      比如在“1→2→3”的2前面插4,只需要让1的钩子指向4,4的钩子指向2,就变成“1→4→2→3”,其他节点不需要动。
2.4 删除元素的操作
  • 顺序表
    如果要删除第i个元素,需要先把第i个元素去掉,然后把第i+1个及之后的所有元素往前“挪一个位置”(填补空缺),最后更新“已用元素数”。
    比如删除“[1,2,3,4]”的第2个元素(2),需要把3、4往前挪,变成“[1,3,4]”,中间不能留空隙(否则不符合连续空间的特性)。

  • 链表
    如果要删除第i个元素,只需要找到第i-1个节点,把它的钩子从原来指向第i个节点,改成指向第i+1个节点,然后把第i个节点的内存释放掉即可。
    比如删除“1→4→2→3”中的4,只需要让1的钩子直接指向2,4就被“摘”下来了,其他节点位置不变。

2.5 访问元素的效率
  • 顺序表
    因为元素位置能直接计算(第i个元素的位置 = 起点 + i×元素大小),所以访问任意位置的元素时,一步就能找到,效率很高(时间复杂度O(1))。

  • 链表
    因为元素位置靠钩子串联,访问第i个元素时,必须从第一个节点开始,顺着钩子一个个数到第i个,效率较低(时间复杂度O(n))。

3.总结

顺序表的底层是“连续内存”,决定了它的实现依赖“空间预分配+位置计算”,操作时需要挪动元素但访问快;
链表的底层是“离散节点+指针”,决定了它的实现依赖“动态创建+指针串联”,操作时无需挪动元素但访问慢。
这种底层结构的差异,是两者实现方式和性能特性的根本原因。

二.头文件list.h

#pragma once
#include<iostream>
using namespace std;namespace yl
{//定义单个结点结构template<typename T>struct _list_node{_list_node<T>* _prev;_list_node<T>* _next;T _data;_list_node(const T& x):_data(x), _prev(nullptr), _next(nullptr){}};

1. 命名空间与模板

  • 代码位于yl命名空间内,避免命名冲突
  • 使用模板template<typename T>实现泛型,支持任意数据类型

2. 核心数据结构

  • _list_node结构体表示链表的节点
  • 包含三个成员变量:
    • _prev:指向前驱节点的指针
    • _next:指向后继节点的指针
    • _data:存储节点数据的模板类型变量

3. 构造函数

  • 带参数的构造函数_list_node(const T& x)
  • 初始化节点数据_data为传入值
  • _prev_next指针初始化为nullptr

设计特点

  • 双向链表结构,支持双向遍历
  • 节点独立管理前后连接关系
  • 模板设计保证了良好的扩展性
 // 链表迭代器模板// T: 数据类型,Ref: 引用类型,Ptr: 指针类型template<typename T, class Ref, class Ptr>struct _list_iterator{typedef _list_iterator<T, Ref, Ptr> Self;  // 自身类型别名typedef _list_node<T> Node;               // 节点类型别名Node* _node;                              // 指向当前节点的指针// 构造函数:用节点指针初始化迭代器_list_iterator(Node* node) : _node(node) {}// 解引用操作符:返回节点数据的引用Ref operator*() { return _node->_data; }// 箭头操作符:返回节点数据的指针Ptr operator->() { return &_node->_data; }// const版本箭头操作符:用于常量迭代器Ptr operator->() const { 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) const {return it._node != this->_node;}// 析构函数:迭代器不拥有节点内存,无需释放~_list_iterator() {}};

以上这段代码实现了双向链表的迭代器

4. 模板参数设计

  • 三个模板参数:T(数据类型)、Ref(引用类型)、Ptr(指针类型)
  • 通过分离引用和指针类型,支持普通迭代器和常量迭代器

5. 核心成员

  • Node* _node:指向当前节点的指针
  • 类型别名:Self(自身类型)和Node(节点类型)

6. 构造与析构

  • 构造函数:接收节点指针初始化迭代器
  • 析构函数:空实现(迭代器不负责内存管理)

7. 操作符重载

  • 解引用操作符*:返回节点数据引用
  • 箭头操作符->:返回节点数据指针(含const版本)
  • 自增操作符++:前置和后置版本(支持双向移动)
  • 自减操作符--:前置和后置版本(支持双向移动)
  • 不等比较!=:比较节点指针是否相等

迭代器特性

  • 双向迭代器:支持前后移动
  • 符合STL迭代器规范(实现必要操作符)
  • 轻量级设计:仅包含一个指针成员

内存管理

  • 迭代器不拥有节点内存
  • 节点生命周期由链表容器管理
template<typename T>class list {public:typedef _list_node<T> Node;             // 链表节点类型typedef _list_iterator<T, T&, T*> iterator;         // 普通迭代器typedef _list_iterator<T, const T&, const T*> const_iterator; // 常量迭代器// 返回指向第一个元素的迭代器iterator begin() { return _head->_next; }// 返回指向尾后位置的迭代器iterator end() { return _head; }// 常量版本的begin()和end()const_iterator begin() const { return const_iterator(_head->_next); }const_iterator end() const { return const_iterator(_head); }// 默认构造函数list() { empty_init(); }// 析构函数:释放链表内存~list() {clear();        // 清空所有数据节点delete _head;   // 释放头节点}// 拷贝构造函数list(const list<T>& lt) {empty_init();           // 初始化空链表for (auto& e : lt) {    // 逐个复制元素push_back(e);}}

这段代码实现了双向链表的容器类,下面是重点内容概括:

8. 类型定义

  • 嵌套类型定义:Node(节点类型)
  • 迭代器类型:
    • iterator:普通迭代器(引用类型T&,指针类型T*
    • const_iterator:常量迭代器(引用类型const T&,指针类型const T*

9. 迭代器接口

  • begin():返回指向第一个元素的迭代器
  • end():返回指向尾后位置的迭代器
  • 提供常量版本,支持常量对象遍历

10. 内存管理

  • 哨兵节点(头节点_head)设计:
    • 空链表时_head->_next == _head
    • 简化边界条件处理
  • 析构函数:
    • 调用clear()释放所有数据节点
    • 释放头节点内存

11. 构造函数

  • 默认构造函数:调用empty_init()初始化空链表
  • 拷贝构造函数:
    • 初始化空链表
    • 通过范围for循环逐个复制元素

. 关键方法

  • empty_init():初始化头节点,构建循环链表
  • clear():清空所有数据节点但保留头节点
        // 初始化列表构造函数list(initializer_list<T> il) {empty_init();           // 初始化空链表for (auto& e : il) {    // 使用初始化列表中的元素填充链表push_back(e);}}// 交换两个链表的内容void swap(list<T> lt) {std::swap(_head, lt._head);     // 交换头节点指针std::swap(_size, lt._size);     // 交换元素数量}// 赋值运算符重载list<T>& operator=(const list<T> il) {swap(il);         // 通过交换实现拷贝赋值return *this;}// 初始化空链表void empty_init() {_head = new Node(T());       // 创建头节点,初始化为T的默认值_head->_next = _head;        // 头节点的next指向自身_head->_prev = _head;        // 头节点的prev指向自身_size = 0;                   // 链表大小初始化为0}// 清空链表但保留头节点void clear() {iterator it = begin();while (it != end()) {        // 遍历所有数据节点it = erase(it);          // 删除当前节点并获取下一个节点}}

以上cpp代码继续完善了双向链表容器类,新增了初始化列表构造、赋值运算符等功能:

12. 初始化列表构造函数

  • 支持list<int> lst = {1, 2, 3}语法
  • 调用empty_init()初始化头节点
  • 通过范围for循环和push_back()逐个添加元素

13. 交换方法

  • swap(list<T> lt):交换两个链表的内容
  • 直接交换头节点指针和元素数量
  • 时间复杂度O(1)

14. 赋值运算符重载

  • 采用拷贝并交换(Copy-and-swap)惯用法
  • 通过值传递接收参数,自动处理自我赋值问题
  • 高效释放原有资源并获取新资源

15. 链表初始化

  • empty_init()
    • 创建头节点,初始化为T()
    • 构建循环链表结构(_headprevnext指向自身)
    • 初始化_size为0

16. 清空操作

  • clear()
    • 使用迭代器遍历所有数据节点
    • 调用erase(it)删除节点并更新迭代器
    • 保留头节点,保持链表结构完整性
// 在链表头部插入元素void push_front(const T& x) { insert(begin(), x); }// 在链表尾部插入元素void push_back(const T& x) { insert(end(), x); }// 删除链表尾部元素void pop_back() { erase(--end()); }// 删除链表头部元素void pop_front() { erase(begin()); }// 在指定位置前插入元素,返回新节点的迭代器iterator insert(iterator pos, const T& x) {Node* cur = pos._node;              // 当前位置的节点Node* newnode = new Node(x);        // 创建新节点Node* prev = cur->_prev;            // 当前位置的前一个节点// 调整指针连接新节点prev->_next = newnode;newnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;_size++;                            // 更新链表大小return iterator(newnode);           // 返回指向新节点的迭代器}// 删除指定位置的节点,返回下一个位置的迭代器iterator erase(iterator pos) {Node* cur = pos._node;              // 当前位置的节点Node* prev = cur->_prev;            // 前一个节点Node* next = cur->_next;            // 下一个节点// 调整指针跳过当前节点prev->_next = next;next->_prev = prev;delete cur;                         // 释放当前节点内存_size--;                            // 更新链表大小return iterator(next);              // 返回下一个位置的迭代器}private:Node* _head;           // 头节点指针(哨兵节点)size_t _size = 0;      // 链表元素数量};
}

以上代码完善了双向链表的核心操作接口:

17. 首尾操作

  • push_front/push_back:通过insert在首尾插入元素
  • pop_front/pop_back:通过erase删除首尾元素
  • 时间复杂度均为O(1)

18. 插入操作

  • insert(iterator pos, const T& x)
    • pos前插入新节点
    • 调整四个指针完成插入
    • 返回指向新节点的迭代器
  • 保持迭代器有效性(除被插入位置外)

19. 删除操作

  • erase(iterator pos)
    • 删除pos指向的节点
    • 调整两个指针跳过待删节点
    • 释放节点内存并返回下一位置迭代器
  • 注意:删除后原迭代器失效

指针调整逻辑

  • 插入时需修改四个指针:前驱节点的next、新节点的prev/next、后继节点的prev
  • 删除时需修改两个指针:前驱节点的next、后继节点的prev
  • 头节点参与循环链表维护

数据成员

  • Node* _head:哨兵节点,构成循环链表
  • size_t _size:记录元素数量,插入/删除时维护

三.头文件test.cpp

#include"list.h"// 打印链表内容的模板函数
template<class T>
void print(const yl::list<T>& lt) {auto it = lt.begin();while (it != lt.end()) {cout << *it << " ";++it;}cout << endl;
}// 测试函数1:测试基本功能
void test01() {yl::list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);lt1.push_back(5);print(lt1);
}// 测试函数2:测试拷贝构造和初始化列表
void test02() {yl::list<int> lt1 = { 0, 1, 2, 3, 4, 5 };yl::list<int> lt2 = lt1;print(lt2);
}

1. 打印函数

  • 模板函数print(const yl::list<T>& lt)
  • 使用迭代器遍历链表并输出元素
  • 支持任意可输出类型(需重载operator<<

2. 测试函数1

  • 功能:测试基本插入操作
  • 步骤
    1. 创建空链表lt1
    2. 尾插5个元素(1-5)
    3. 打印链表(预期输出:1 2 3 4 5)
  • 验证点
    • push_back功能
    • 迭代器遍历正确性
  1. 测试函数2
    • 功能:测试初始化列表和拷贝构造
    • 步骤
      1. 使用初始化列表构造lt1(元素0-5)
      2. 通过拷贝构造创建lt2
      3. 打印lt2(预期输出:0 1 2 3 4 5)
    • 验证点
      • 初始化列表构造函数
      • 拷贝构造函数(深拷贝)
// 测试函数3:测试迭代器操作
void test03() {yl::list<int> lt;lt.push_back(10);lt.push_back(20);lt.push_back(30);cout << "测试前置++: ";auto it = lt.begin();++it;cout << *it << endl;cout << "测试后置++: ";it = lt.begin();it++;cout << *it << endl;cout << "测试前置--: ";it = lt.end();--it;cout << *it << endl;cout << "测试后置--: ";it = lt.end();it--;cout << *it << endl;
}// 测试函数4:测试插入和删除操作
void test04() {yl::list<int> lt;lt.push_back(1);lt.push_back(3);lt.push_back(4);auto it = lt.begin();++it;lt.insert(it, 2);cout << "插入后: ";print(lt);it = lt.begin();++it;lt.erase(it);cout << "删除后: ";print(lt);
}int main() {cout << "=== 测试基本功能 ===" << endl;test01();cout << "\n=== 测试拷贝构造和初始化列表 ===" << endl;test02();cout << "\n=== 测试迭代器操作 ===" << endl;test03();cout << "\n=== 测试插入和删除操作 ===" << endl;test04();return 0;
}

这段代码新增了迭代器操作和插入删除功能的测试,以下是重点内容概括:

3. 测试函数3:迭代器操作测试

  • 功能:验证迭代器自增自减操作
  • 步骤
    1. 创建链表lt并插入元素10, 20, 30
    2. 测试前置++:移动到第二个元素(输出20
    3. 测试后置++:移动到第二个元素(输出20
    4. 测试前置--:从end()移动到最后一个元素(输出30
    5. 测试后置--:从end()移动到最后一个元素(输出30
  • 验证点
    • 双向迭代器的移动正确性
    • 前置/后置操作符的语义差异

4. 测试函数4:插入删除测试

  • 功能:验证插入删除接口
  • 步骤
    1. 创建链表lt并插入元素1, 3, 4
    2. 在第二个位置插入2(链表变为1, 2, 3, 4
    3. 删除第二个位置元素(链表变为1, 3, 4
  • 验证点
    • insert在指定位置前插入元素
    • erase正确删除元素并返回下一位置迭代器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/916308.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/916308.shtml
英文地址,请注明出处:http://en.pswp.cn/news/916308.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【595驱动8*8点阵】2022-9-11

缘由LED点阵屏只能一次亮一列-嵌入式-CSDN问答 #include "REG52.h" sbit dsP1^0;//数据线 595的14脚 sbit shP1^1;//数据输入时钟线 595的11脚 sbit stP1^2;//输出存储器锁存时钟线 595的12脚 void QuDong595(unsigned char sj) {unsigned char aa8;while(aa--){ds…

AI总结视频以及谷歌浏览器插件安装步骤

本篇介绍用AI一键总结全网视频内容的独家方法&#xff0c;支持B站、抖音、小红书等任何平台的视频&#xff0c;提高学习效率&#xff0c;帮助一键提取视频文案、划分章节&#xff0c;还能生成双语翻译&#xff0c;这个方法直接在线总结所有视频。 一.准备工作&#xff1a; 需要…

网络协议HTTP、TCP

概述如何让数据具有自我描述性?为什么网络有层级的划分?交换机、路由器要不要阅读一个信息的头部&#xff1f;要不要阅读数据部分&#xff1f; 网卡&#xff1a;网卡可以完成帧的封装和解封装&#xff0c;工作在数据链路层。 中继器&#xff1a;中继器以比特方式将网络信号进…

Linux选择题

第12题&#xff08;多选题&#xff09;原题: 能够为逻辑卷增加容量的命令有( )。A. lvresize: 此命令可以用来调整逻辑卷的大小&#xff0c;既可以增大也可以缩小。例如&#xff0c;lvresize -L 1G /dev/vgname/lvname 会增加1GB&#xff0c;lvresize -L 10G /dev/vgname/lvnam…

使用钉钉开源api发送钉钉工作消息

在工作管理系统场景中&#xff0c;上下级和不同部门之间常常有请假&#xff0c;餐补等流程操作&#xff0c;而这些操作通常需要人员手动进行&#xff0c;这里我们引入一个钉钉的api&#xff0c;可以基于钉钉来发送工作消息通知1、导入钉钉sdk<dependency><groupId>…

拒绝SQL恐惧:用Python+pyqt打造任意Excel数据库查询系统

一、引言 在数字化转型浪潮中&#xff0c;超过76%的基层业务人员仍被困在"SQL恐惧症"的泥潭里——他们精通业务逻辑却受限于技术门槛&#xff0c;面对海量数据时只能反复请求IT部门协助。本项目通过PythonPyQt来构建基于Excel风格的查询系统&#xff0c;从而打破这种…

KubeKey安装KubeSphere、部署应用实践问题总结

使用KubeSphere的KubeKey 安装K8s 集群过程中&#xff0c;碰到了一些问题&#xff0c;现在都一一解决了&#xff0c;以此记录一下。 kubekey 安装k8s 集群报错 execute task timeout, Timeout1m error: Pipeline[CreateClusterPipeline] execute failed: Module[GreetingsModul…

基于粒子群优化的PID控制在药液流量控制系统中的应用

基于粒子群优化的PID控制在药液流量控制系统中的应用 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家,觉得好请收藏。点击跳转到网站。 1. 引言 在现代工业控制系统中,精确的流量控制是许多生产过程的关键环节。本文针对药液流量控制…

不用电脑要不要关机?

1. 短时间不用&#xff08;午休、临时外出&#xff09;&#xff1a;建议「睡眠」或「休眠」睡眠&#xff1a;电脑暂停工作&#xff0c;唤醒速度快&#xff0c;耗电较少适合需要快速恢复工作的场景休眠&#xff1a;整机断电&#xff0c;唤醒速度比睡眠慢&#xff0c;但完全不耗电…

【Spring AI】SiliconFlow-硅基流动

硅基流动 https://docs.siliconflow.cn/cn/userguide/introduction

swagger基本注解@Tag、@Operation、@Parameters、@Parameter、@ApiResponse、@Schema

swagger基本注解 Tag 介绍&#xff1a;用于给接口分组&#xff0c;用途类似于为接口文档添加标签。用于&#xff1a;方法、类、接口。常用属性&#xff1a; name&#xff1a;分组的名称 RestController RequestMapping("/sysUser") Tag(name "管理员接口&quo…

Unity 实现帧率(FPS)显示功能

一、功能介绍本教程实现一个 FPS 显示脚本&#xff0c;支持 TextMeshProUGUI 组件。脚本会每秒更新一次帧率&#xff0c;并显示在 UI 上&#xff0c;便于开发和调试时观察性能变化。二、完整代码将以下代码保存为 FPS.cs 脚本&#xff1a;using UnityEngine; using TMPro;[Requ…

【星野AI】minimax非活动时间充值优惠漏洞

点开发现有活动即将开启。把手机时间修改为20250729&#xff0c;或者其它活动内时间。发现活动的充值接口未进行时间校验。叠加新人首充优惠&#xff0c;充值六元&#xff0c;获得1800钻。在非活动时间获取了优惠。

Python 程序设计讲义(22):循环结构——for 循环

Python 程序设计讲义&#xff08;22&#xff09;&#xff1a;循环结构——for 循环 目录Python 程序设计讲义&#xff08;22&#xff09;&#xff1a;循环结构——for 循环一、for 循环的语法二、for 循环执行的流程三、for 循环应用举例while 循环的循环次数往往是不确定的&am…

自动驾驶---视觉语言模型(VLM)引导的模型预测控制器(MPC)

1 背景之前大家普遍认为的端到端就是传感器输入&#xff0c;控制输出&#xff0c;这也确实是真正的端到端&#xff0c;但目前车企走的更多的是轨迹生成。自动驾驶端到端控制瓶颈主要有以下两点&#xff1a;可解释性缺失&#xff1a;传统端到端模型&#xff08;如纯VLM控制器&am…

最优估计准则与方法(5)加权最小二乘估计(WLS)_学习笔记

前言 最优估计理论中研究的最小二乘估计&#xff08;LS&#xff09;为线性最小二乘估计&#xff08;LLS&#xff09;&#xff0c;包括古典最小二乘估计&#xff08;CLS&#xff09;[1]、加权最小二乘估计&#xff08;WLS&#xff09;和递推最小二乘估计&#xff08;RLS&#x…

Linux——线程互斥

文章目录一、有关概念原子性错误认知澄清加锁二、锁的相关函数全局锁局部锁初始化销毁加锁解锁三、锁相关如何看待锁一个线程在执行临界区的代码时&#xff0c;可以被切换吗&#xff1f;锁是本身也是临界资源&#xff0c;它如何做到保护自己&#xff1f;&#xff08;锁的实现&a…

扣子(Coze)宣布开源两大核心项目——Coze Studio(扣子开发平台)和Coze Loop(扣子罗盘),附安装步骤

2025年7月26日,字节跳动旗下AI开发平台“扣子(Coze)”宣布开源两大核心项目——Coze Studio(扣子开发平台)和Coze Loop(扣子罗盘),采用Apache 2.0协议,支持免费商用及本地化部署。 开源内容 Coze Studio:提供可视化AI智能体开发工具,支持零代码/低代码拖拽式工作流编…

InfluxDB Flux 查询协议实战应用(二)

四、实战案例解析4.1 服务器性能监控数据查询在服务器性能监控场景中&#xff0c;InfluxDB 和 Flux 查询协议能够发挥重要作用&#xff0c;帮助运维人员实时了解服务器的运行状态&#xff0c;及时发现性能问题。假设我们的服务器性能监控数据存储在名为server-monitoring的存储…

二层隧道协议(PPP、PPTP、L2TP)

PPP —— 点对点链路上的“链路层会话层”协议&#xff0c;解决拨号认证、IP 分配和多协议封装。PPTP —— 在 IP 网络里开一条“PPP-over-GRE”隧道&#xff0c;把 PPP 封装进公共网络&#xff0c;速度快但已不安全。L2TP —— 在 IP/UDP 里再开一条“PPP-over-UDP”隧道&…