【c++】【STL】list详解
目录
- list的作用
- list的接口
- 构造函数
- 赋值运算符重载
- 迭代器相关
- size
- empty
- front
- back
- assign
- push_front
- pop_front
- push_back
- pop_back
- insert
- erase
- swap
- resize
- clear
- splice
- remove
- remove_if
- unique
- merge
- sort
- reverse
- 关系运算符重载(非成员函数)
- list的模拟实现
- 结点类
- 迭代器类
- typedef的妙用
- *运算符重载
- ->运算符重载
- ++、--运算符重载
- list类
- CreateHead(头节点创建)
- insert
- erase
- 赋值运算符重载
list的作用
list是c++的stl库提供的链表容器,链表作为我们熟知的数据结构之一,其与顺序表相比,在任意位置插入删除方面具有绝对的优势,但在随机读取方面不如顺序表,两者属于互补关系,stl中的list底层是用双向链表实现的,以实现反向迭代器的反向读取,stl中还有forward_list,它是由单向链表实现的。
list的接口
构造函数
//默认构造
explicit list (const allocator_type& alloc = allocator_type());
//指定链表初始化大小和链表初始化的值
explicit list (size_type n, const value_type& val = value_type(),const allocator_type& alloc = allocator_type());
//使用迭代器进行构造
template <class InputIterator>list (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type());
//拷贝构造
list (const list& x);
四种构造方式都较为常用
赋值运算符重载
list& operator= (const list& x);
重载了来链表复制,代码更加易读。
迭代器相关
iterator begin();
const_iterator begin() const;iterator end();
const_iterator end() const;reverse_iterator rbegin();
const_reverse_iterator rbegin() const;reverse_iterator rend();
const_reverse_iterator rend() const;const_iterator cbegin() const noexcept;const_iterator cend() const noexcept;const_reverse_iterator crbegin() const noexcept;const_reverse_iterator crend() const noexcept;
由于链表是非连续性容器,所以迭代器还是很实用的。
size
size_type size() const;
返回链表尺寸。
empty
bool empty() const;
链表判空。
front
reference front();
const_reference front() const;
返回对链表第一个元素的引用。
back
reference back();
const_reference back() const;
返回对链表最后一个元素的引用。
assign
template <class InputIterator>void assign (InputIterator first, InputIterator last);//迭代器初始化
void assign (size_type n, const value_type& val);//指定初始化大小和内容
重新初始化链表。
push_front
void push_front (const value_type& val);
头插。
pop_front
void pop_front();
头删。
push_back
void push_back (const value_type& val);
尾插。
pop_back
void pop_back();
尾删。
insert
//插入一个
iterator insert (iterator position, const value_type& val);//插入一段
void insert (iterator position, size_type n, const value_type& val);//插入迭代器表示的一段
template <class InputIterator>void insert (iterator position, InputIterator first, InputIterator last);
插入函数,链表的插入函数效率很高。
erase
iterator erase (iterator position);//删除一个
iterator erase (iterator first, iterator last);//删除一段
删除函数,链表的删除函数效也很高。
swap
void swap (list& x);
交换函数,交换两个链表。
resize
void resize (size_type n, value_type val = value_type());
重新指定链表的大小,如果n大于链表此时的size,就扩充到n大小,然后将扩充后的节点的值初始化成指定内容(缺省为0);如果n小于链表此时的size,就减小到n大小,然后删除并销毁超出的部分。
clear
void clear();
清空链表。
splice
void splice (iterator position, list& x);//转移一整个
void splice (iterator position, list& x, iterator i);//转移指定位置的元素
void splice (iterator position, list& x, iterator first, iterator last);//转移指定的一段。
将链表中的元素转移到另一个链表中,position是插入位置。
remove
void remove (const value_type& val);
删除链表中所有与给定值相等的元素。
remove_if
template <class Predicate>void remove_if (Predicate pred);
删除链表中所有Predicate pred返回true的元素的函数,这允许我们删除满足特定复杂条件的元素。
unique
void unique();
template <class BinaryPredicate>void unique (BinaryPredicate binary_pred);
这个函数可以让链表中等于特定值或满足特定条件的元素唯一,与remove和remove_if函数类似,只不过他们是全部删除,unique是要留一个。
merge
void merge (list& x);
template <class Compare>void merge (list& x, Compare comp);
将两个已经满足一定顺序的链表合并为一个满足这个顺序的新链表,默认顺序是升序,也就是说合并两个升序链表时可以用第一个函数,其他的都需要写仿函数。
sort
void sort();默认升序
template <class Compare>void sort (Compare comp);//自定义
list自己的排序函数。
reverse
void reverse();
list自己的反转函数。
关系运算符重载(非成员函数)
template <class T, class Alloc>bool operator== (const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
template <class T, class Alloc>bool operator!= (const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
template <class T, class Alloc>bool operator< (const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
template <class T, class Alloc>bool operator<= (const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
template <class T, class Alloc>bool operator> (const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
template <class T, class Alloc>bool operator>= (const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
list的模拟实现
#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;namespace jiunian
{// List的节点类template<class T>struct ListNode{ListNode(const T& val = T()) :_pPrev(nullptr),_pNext(nullptr),_val(val){}ListNode<T>* _pPrev;ListNode<T>* _pNext;T _val;};//List的迭代器类template<class T, class Ref, class Ptr>struct ListIterator{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;ListIterator(PNode pNode = nullptr):_pNode(pNode){}ListIterator(const Self& l):_pNode(l._pNode){}Ref operator*(){return _pNode->_val;}Ptr operator->(){return &(_pNode->_val);}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){Self tmp(*this);_pNode = _pNode->_pNext;return tmp;}Self& operator--(){_pNode = _pNode->_pPrev;return *this;}Self& operator--(int){Self tmp(*this);_pNode = _pNode->_pPrev;return tmp;}bool operator!=(const Self& l){return _pNode != l._pNode;}bool operator==(const Self& l){return _pNode == l._pNode;}PNode _pNode;};//list类template<class T>class list{typedef ListNode<T> Node;typedef Node* PNode;public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;public:///// List的构造 list(){CreateHead();}list(int n, const T& value = T()){CreateHead();while(n--){push_back(value);}}template <class Iterator>list(Iterator first, Iterator last){CreateHead();while (first != last){push_back(*(first++));}}list(const list<T>& l){CreateHead();for (auto& e : l){push_back(e);}}list<T>& operator=(list<T> l){swap(l);return *this;}~list(){clear();delete _pHead;_pHead = nullptr;}///// List Iteratoriterator begin(){return _pHead->_pNext;}iterator end(){return _pHead;}const_iterator begin()const{return _pHead->_pNext;}const_iterator end()const{return _pHead;}///// List Capacitysize_t size()const{return _size;}bool empty()const{return _pHead == _pHead->_pNext;//size == 0;}// List AccessT& front(){return _pHead->_pNext->_val;}const T& front()const{return _pHead->_pNext->_val;}T& back(){return _pHead->_pPrev->_val;}const T& back()const{return _pHead->_pPrev->_val;}// List Modifyvoid push_back(const T& val){ insert(end(), val); }void pop_back() {erase(--end()); }void push_front(const T& val){insert(begin(), val); }void pop_front() {erase(begin()); }// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){Node* newnode = new Node(val);newnode->_pPrev = pos._pNode->_pPrev;newnode->_pNext = pos._pNode;pos._pNode->_pPrev->_pNext = newnode;pos._pNode->_pPrev = newnode;++_size;return newnode;}//iterator insert(iterator pos, const T& x)//{// Node* cur = pos._pNode;// Node* prev = cur->_pPrev;// Node* newnode = new Node(x);// prev->_pNext = newnode;// newnode->_pNext = cur;// cur->_pPrev = newnode;// newnode->_pPrev = prev;// //++_size;// return newnode;//}// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){pos._pNode->_pNext->_pPrev = pos._pNode->_pPrev;pos._pNode->_pPrev->_pNext = pos._pNode->_pNext;iterator ret = pos._pNode->_pNext;delete pos._pNode;--_size;return ret;}void clear(){iterator cur = begin();while (cur != end()){cur = erase(cur);}_size = 0;}void swap(list<T>& l){std::swap(_pHead, l._pHead);std::swap(_size, l._size);}private:void CreateHead(){_pHead = new Node;_pHead->_pNext = _pHead;_pHead->_pPrev = _pHead;}PNode _pHead;size_t _size = 0;};
};
对于list这种存储不连续的容器,其迭代器的实现就不能像string和vector一样直接对指针进行封装,虽然对于迭代器来说,其底层的实现离不开指针,但其还是有别于string和vector的。
结点类
在对于迭代器进行说明之前,我还是要先介绍一下链表的结点类,结点是组成链表的基本单位,是需要单独封装的。
// List的节点类
template<class T>
struct ListNode
{ListNode(const T& val = T()) :_pPrev(nullptr),_pNext(nullptr),_val(val){}ListNode<T>* _pPrev;ListNode<T>* _pNext;T _val;
};
由于我们创建的是一个双向带头链表,所以一个节点要给一个指针指向前一个结点,也要给一个指针指向后一个节点,再者因为ListNode中的成员之后都要被list类频繁使用,所以我们直接将类定义成struct,因为struct的元素在不加访问限定符的情况下都是默认共有的(兼容c语言)。最后我们为这个类写上构造函数就完成了。
迭代器类
//List的迭代器类
template<class T, class Ref, class Ptr>
struct ListIterator
{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;ListIterator(PNode pNode = nullptr):_pNode(pNode){}ListIterator(const Self& l):_pNode(l._pNode){}Ref operator*(){return _pNode->_val;}Ptr operator->(){return &(_pNode->_val);}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){Self tmp(*this);_pNode = _pNode->_pNext;return tmp;}Self& operator--(){_pNode = _pNode->_pPrev;return *this;}Self& operator--(int){Self tmp(*this);_pNode = _pNode->_pPrev;return tmp;}bool operator!=(const Self& l){return _pNode != l._pNode;}bool operator==(const Self& l){return _pNode == l._pNode;}PNode _pNode;
};
之后就是迭代器的说明了,在有了对于string和vector的实现经验之后,其实对于list这个类本身的实现已经很轻松了,因为stl库中的容器之间是有很强的共性的,实现的思路大差不差,但对于list的迭代器还是有所不同的,因为list要实现不连续内存容器的随机访问。首先我们看向这个类所给的模板参数,有三个,这其实是一个令人疑惑的点,因为通常来说我们只需要给一个模板参数说明迭代器指向的节点中的val是什么类型不就行了,但这里所给的参数有足足三个,这里直接理解是理解不同的,我们不妨先往下看。
typedef的妙用
typedef ListNode<T>* PNode;
typedef ListIterator<T, Ref, Ptr> Self;
这两句代码我想要单独拎出来讲,如果我们有一些阅读源码的经历,我们会发现写源码的那些大佬会经常性的使用typedef,一层套一层,看起来像是脱裤子放屁,但其实不然,比如这里,假如我们不使用typedef,那会阻碍我们书写代码吗?答案是不会的,typedef无非只是个替换,不使用无非只是麻烦一点,多写几个模板参数实例化的事(其实省事这一点就足以成为我们使用它的理由了),但倘若我们书写完代码之后因为某些原因要改变ListNode或ListIterator的模板参数数量或者模板参数名就麻烦了,我们要把之前写ListNode和ListIterator都写一遍,如果代码量巨大,那将是一场噩梦,但倘若我们用了typedef,不仅书写时就省了事,书写之后万一要对typedef的内容进行更改也是很轻松的,只要把typedef的地方一改其他地方都会改。说到底,这样写本质上降低了代码之间的关联度(耦合度),我们作为代码学习者,可能会从某些地方听说过高内聚低耦合的概念,高内聚低耦合就是指尽量使一个模块的代码专注于完成单一任务,且模块与模块之间的关联度尽可能地低。我们这里使用typedef就大大地降低了代码之间的关联度,这样一处代码的修改带来的连锁反应会尽可能地小,这是我们在书写代码时要时刻注意的。
*运算符重载
Ref operator*()
{return _pNode->_val;
}
这段代码是对于*的运算符重载这不难看出,但是我们看想这个函数的返回值,只是我们之前所说的三个模板参数中的第二个,我们仔细想想,倘若这里不使用模板参数,我们应该写什么呢?当然是_val类型的引用,解引用运算符之后的变量更改会影响原指针指向的数,所以要用引用。但为什么要用模板参数呢,这时我们看向list类的这一段,
typedef ListIterator<T, T&, T*> iterator;
typedef ListIterator<T, const T&, const T*> const_iterator;
对于迭代器来说,不仅有普通迭代器,还有const版的,而普通迭代器和const迭代器除了*和->运算符重载不一样之外,其他的都是一致的,所以我们通过传三个参数的方式成功偷了一波懒,一个类干了别人两个类干的事,剩下的事由编译器来完成。
->运算符重载
Ptr operator->()
{return &(_pNode->_val);
}
这个函数可以访问_val的对象成员(前提是_val得有对象成员,没有用不到),这个函数笔者在一开始理解时非常困惑,因为笔者认为迭代器视为指向链表结点的指针,而->被用来在使用指针的情况下访问对象元素,所以这个->是用来访问系欸但元素的,也就是_val、_pPrev和_pNext,但事实上不是,这里迭代器不应该被看作为一个指向结点的指针,而应该看作为一个指向_val的指针,因为我是在实现这个类的基础之上去理解这个迭代器的,我先入为主了,最为使用者来说,我并不清楚list类的底层如何实现,我也就不用会知道list其实有一个前置的类叫ListNode,也并不知道ListNode中有三个元素_val、_pPrev和_pNext,在使用者看来,迭代器就是指向容器元素本身,使用->访问的就是元素这个对象本身的元素(前提是有元素)。理解了这个函数本身的作用之后,我们看向这个函数的返回值,返回值类型使用了单独的模板参数,这在前一个解引用运算符重载中讲过了,这里也是如此,
typedef ListIterator<T, T&, T*> iterator;
typedef ListIterator<T, const T&, const T*> const_iterator;
这里的Ptr指的T*(或const T*)。我们再看向返回值本身,_pNode->_val取地址,这个函数返回之后会发生什么呢,假如我们写了以下代码
std::cout << it->a << std::endl;
it->使用运算符重载返回了一个指针,那代码就变成了一个指针和一个元素中间没有运算符,这因该是会报错的操作,但这里是会正常编译通过的,因为c++在这里又做了特殊处理给这两个变量中间加上了一个->,所以时候事实上来说代码应该是这样的
std::cout << it->->a << std::endl;//演示一下,事实上会报错
可以看出c++为了增加代码可读性还是做出了很多妥协的。
++、–运算符重载
Self& operator++()
{_pNode = _pNode->_pNext;return *this;
}Self operator++(int)
{Self tmp(*this);_pNode = _pNode->_pNext;return tmp;
}Self& operator--()
{_pNode = _pNode->_pPrev;return *this;
}Self& operator--(int)
{Self tmp(*this);_pNode = _pNode->_pPrev;return tmp;
}
之后还要说明的就是迭代器的++和–的运算符重载,因为之前我们也说过,list是内存不连续的容器,所以++和–运算符都不能直接以指针++和–的形式实现,而是使用ListNode中_pPrev和_pNext指针来实现迭代,至于前置++(–)和后置++(–)的书写区别,之前的文章也讲过,因为它们是单参运算符,无法通过位置识别从而进行不同的操作,所以c++特别规定++(–)运算符重载时在参数列表多加上int的是后置++(–),没加的是前置++(–)。
list类
template<class T>
class list
{typedef ListNode<T> Node;typedef Node* PNode;
public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;
public:///// List的构造 list(){CreateHead();}list(int n, const T& value = T()){CreateHead();while(n--){push_back(value);}}template <class Iterator>list(Iterator first, Iterator last){CreateHead();while (first != last){push_back(*(first++));}}list(const list<T>& l){CreateHead();for (auto& e : l){push_back(e);}}list<T>& operator=(list<T> l){swap(l);return *this;}~list(){clear();delete _pHead;_pHead = nullptr;}///// List Iteratoriterator begin(){return _pHead->_pNext;}iterator end(){return _pHead;}const_iterator begin()const{return _pHead->_pNext;}const_iterator end()const{return _pHead;}///// List Capacitysize_t size()const{return _size;}bool empty()const{return _pHead == _pHead->_pNext;//size == 0;}// List AccessT& front(){return _pHead->_pNext->_val;}const T& front()const{return _pHead->_pNext->_val;}T& back(){return _pHead->_pPrev->_val;}const T& back()const{return _pHead->_pPrev->_val;}// List Modifyvoid push_back(const T& val){ insert(end(), val); }void pop_back() {erase(--end()); }void push_front(const T& val){insert(begin(), val); }void pop_front() {erase(begin()); }// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){Node* newnode = new Node(val);newnode->_pPrev = pos._pNode->_pPrev;newnode->_pNext = pos._pNode;pos._pNode->_pPrev->_pNext = newnode;pos._pNode->_pPrev = newnode;++_size;return newnode;}//iterator insert(iterator pos, const T& x)//{// Node* cur = pos._pNode;// Node* prev = cur->_pPrev;// Node* newnode = new Node(x);// prev->_pNext = newnode;// newnode->_pNext = cur;// cur->_pPrev = newnode;// newnode->_pPrev = prev;// //++_size;// return newnode;//}// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){pos._pNode->_pNext->_pPrev = pos._pNode->_pPrev;pos._pNode->_pPrev->_pNext = pos._pNode->_pNext;iterator ret = pos._pNode->_pNext;delete pos._pNode;--_size;return ret;}void clear(){iterator cur = begin();while (cur != end()){cur = erase(cur);}_size = 0;}void swap(list<T>& l){std::swap(_pHead, l._pHead);std::swap(_size, l._size);}private:void CreateHead(){_pHead = new Node;_pHead->_pNext = _pHead;_pHead->_pPrev = _pHead;}PNode _pHead;size_t _size = 0;
};
list类的实现就比较公式化了,值得一说的就几个,下面一一讲解。
CreateHead(头节点创建)
void CreateHead()
{_pHead = new Node;_pHead->_pNext = _pHead;_pHead->_pPrev = _pHead;
}
首先是CreateHead(),这个函数被用于创建头节点,我们实现的list的底层是带头双向链表,头节点是必须的,这个函数在很多成员函数中都会用到,所以单独封装并放进private访问限定符中限制外部访问。函数实现思路也很简单,new一个节点出来,指针首尾相连就行。
insert
iterator insert(iterator pos, const T& val)
{Node* newnode = new Node(val);newnode->_pPrev = pos._pNode->_pPrev;newnode->_pNext = pos._pNode;pos._pNode->_pPrev->_pNext = newnode;pos._pNode->_pPrev = newnode;++_size;return newnode;
}
之后是insert函数,insert函数可以被反复复用到一些成员函数之中,十分方便。实现思路就是创建一个节点插入pos迭代器指向的节点的前面,接一下指针就行,之后返回新插入的结点防止迭代器失效。
erase
iterator erase(iterator pos)
{pos._pNode->_pNext->_pPrev = pos._pNode->_pPrev;pos._pNode->_pPrev->_pNext = pos._pNode->_pNext;iterator ret = pos._pNode->_pNext;delete pos._pNode;--_size;return ret;
}
erase函数也可以被复用到一些成员函数之中,非常方便,实现思路就是将pos指向的结点的前一个和后一个相接之后删除这个结点,之后返回原本pos指向的结点的下一个结点。
赋值运算符重载
list<T>& operator=(list<T> l)
{swap(l);return *this;
}
赋值运算符重载,这里我们故意不用引用,这样传过来的参数就是拷贝构造好的需要被赋值成的对象,直接交换,由于临时变量的生命周期出了作用域就没了,所以正好把之前的对象的销毁,完美完成交换。
相关文章:
【c++】【STL】list详解
目录 list的作用list的接口构造函数赋值运算符重载迭代器相关sizeemptyfrontbackassignpush_frontpop_frontpush_backpop_backinserteraseswapresizeclearspliceremoveremove_ifuniquemergesortreverse关系运算符重载(非成员函数) list的模拟实现结点类迭…...
redis 数据类型新手练习系列——List类型
redis 数据类型 Redis 主要支持以下几种数据类型: (1)string(字符串): 基本的数据存储单元,可以存储字符串、整数或者浮点数。 (2)hash(哈希):一个键值对集…...
文章记单词 | 第52篇(六级)
一,单词释义 grasp:英 [ɡrɑːsp] 美 [ɡrsp],v. 抓住;紧握;理解;领会;n. 紧握;控制;理解glue:英 [ɡluː] 美 [ɡluː],n. 胶水;胶…...
【今日三题】kotori和气球(排列) / 走迷宫(BFS最短路) / 主持人调度(二)(贪心+优先级队列)
⭐️个人主页:小羊 ⭐️所属专栏:每日两三题 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 kotori和气球(排列)走迷宫(BFS最短路)主持人调度(二)(贪心优先级队列) kotori和气球(排列) kotori和…...
Mysql数据库高可用解决方案-Mysql Router
目录 一.MySQL Router介绍 1. 什么是 MySQL Router? 2. MySQL Router 的主要用途 3. MySQL Router 的工作原理 4. MySQL Router 的核心组件 5. MySQL Router 的部署和配置 6. MySQL Router 的优势 7. 注意事项 8. MySQL Router 与其他工具的对比 9. 总结 …...
windows系统 压力测试技术
一、CPU压测模拟 工具:CpuStres v2.0 官网:https://learn.microsoft.com/en-us/sysinternals/downloads/cpustres 功能:是一个工具类,用来模拟在一个进程中启动最多64个线程,且可以独立控制任何一个线程的启动/暂停、…...
汽车免拆诊断案例 | 2015款奔驰C200L车发动机起动延迟
故障现象 一辆2015款奔驰C200L车,搭载274发动机,累计行驶里程约为15.6万km。该车发动机起动延迟,且发动机故障灯异常点亮。 故障诊断 用故障检测仪检测,发动机控制单元中存储有故障代码“P001685 进气凸轮轴(气缸…...
Python AI图像艺术创作:核心技术与实践指南
Python与AI技术的结合为图像艺术创作开辟了全新维度,通过生成对抗网络(GANs)、扩散模型(如Stable Diffusion)和神经风格迁移等技术,创作者可以轻松生成具有高度创意和艺术性的图像作品。 这些技术不仅突破了传统艺术创作的局限性,还大幅降低了专业创作门槛,使艺术创作…...
比亚迪再获国际双奖 以“技术为王”书写中国汽车出海新篇章
近日,全球汽车行业权威奖项“2025世界汽车大奖”(World Car Awards)在纽约国际车展举行颁奖典礼,比亚迪海鸥(BYD SEAGULL/BYD DOLPHIN MINI)摘得“2025世界城市车(World Urban Car)”…...
虚幻商城 Quixel 免费资产自动化入库(2025年版)
文章目录 一、背景二、问题讲解1. Quixel 免费资产是否还能一键入库?2. 是不是使用了一键入库功能 Quixel 的所有资产就能入库了?3. 一键入库会入库哪些资产?三、实现效果展示四、实现自动化入库五、常见问题1. 出现401报错2. 出现429报错3. 入库过于缓慢4. 入库 0 个资产一…...
斯坦福RGA软件 老版本和兼容Windows 11版本可选
斯坦福RGA软件 老版本和兼容Windows 11版本可选...
RHCSA Linux 系统 文件系统权限
1. 文件的一般权限 (1)文件权限标识解读 drwxr - xr - x. 12 root root 144 Feb 17 16:51 usr ➤d:文件类型(d 表示目录) ➤rwx:文件所有者权限(读 r,写 w,执行 x&am…...
【补题】Codeforces Global Round 20 D. Cyclic Rotation
题意:偷懒 思路: D. Cyclic Rotation - Yaqu - 博客园 1.有个观察,如果操作过的序列,一定是连续相同的数字,当然这不代表一定操作过了,由于操作过1次后连续就没有意义,可以假设全都操作…...
2025年“深圳杯”数学建模挑战赛C题-分布式能源接入配电网的风险分析
布式能源接入配电网的风险分析 小驴数模 背景知识: 随着我国双碳目标的推进,可再生分布式能源在配电网中的大规模应用不可避免,这对传统配电网运行提出挑战。为了量化分析配电网中接入分布式能源的风险,需要对其进行建模与分析…...
微调 LLaMA 2:定制大型语言模型的分步指南
微调 LLaMA 2:定制大型语言模型的分步指南 深入了解如何运用新技术在 Google Colab 平台上对 Llama-2 进行微调操作,从而有效克服内存与计算方面的限制,让开源大型语言模型变得更加易于获取和使用。自从 Meta 发布了 LLaMA 的首个版本后&…...
react-11使用vscode开发react相关扩展插件(相关的快捷生成)
1.快速搭建react组件模板 2.相关搭建命令 2.1 导入导出 前缀方法imp→import moduleName from moduleimn→import moduleimd→import { destructuredModule } from moduleime→import * as alias from moduleima→import { originalName as aliasName} from moduleexp→expo…...
人工智能数学基础(六):数理统计
数理统计是人工智能中数据处理和分析的核心工具,它通过收集、分析数据来推断总体特征和规律。本文将系统介绍数理统计的基本概念和方法,并结合 Python 实例,帮助读者更好地理解和应用这些知识。资源绑定附上完整资源供读者参考学习࿰…...
组网技术知识点
1.port-isloate enable命令用于实现两个接口之间的二层数据隔离,三层数据互通。 2.交换机最多支持4096个VLAN,编号为1-4094 3.display bfd session all:查看BFD会话状态是否UP 4.RJ45通过双绞线连接以太网; AUI端口࿱…...
常用电机类型及其特点对比
1. 直流电机 直流电机里边固定有环状永磁体,电流通过转子上的线圈产生安培力,当转子上的线圈与磁场平行时,再继续转受到的磁场方向将改变,因此此时转子末端的电刷跟转换片交替接触,从而线圈上的电流方向也改变&#x…...
SVTAV1源码-set_all_ref_frame_type
set_all_ref_frame_type函数的主要作用是为当前图像设置所有可能用到的参考帧类型,并将这些参考帧类型存储到一个数组中,同时记录总共有多少个参考帧类型,以下是该函数的各部分解释: 初始化和准备 MvReferenceFrame rf[2]; *tot_r…...
Can‘t create thread to handle bootstrap
MySQL在docker里面启动失败 关键性报错Cant create thread to handle bootstrap rootubuntu:/data# docker logs 6835ec900d8c 2025-04-30 23:29:4308:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.42-1.el9 started. 2025-04-30 23:29:4308:00 [Note] […...
用Power shell脚本批量发布rdl文件到SQL Server Reporting Service
本文用于介绍如何用Power shell脚本批量发布rdl文件到SQL Server Reporting Service. 用户可根据自己的需要创建类似Publish_All_SSRS.ps1的脚本。 目录 1. 目录结构 2. 创建Base_PublishSSRS.ps1 3. 创建Publish_All_SSRS.ps1 4.注意事项 1. 目录结构 目录结构ÿ…...
2025-03 机器人等级考试四级理论真题 4级
1 2025年蛇年春晚,节目《秧BOT》机器人舞蹈表演节目点燃了全国观众的热情,请问参加节目表演的机器人是由哪家公司研发?( ) A.大疆 B.华为 C.优必选 D.宇树科技 【参考答…...
12.SpringDoc OpenAPI 功能介绍(用于生成API接口文档)
12.SpringDoc OpenAPI 功能介绍(用于生成API接口文档) SpringDoc OpenAPI 是一个基于 OpenAPI 3.0/3.1 规范的工具,用于为 Spring Boot 应用生成 API 文档。它是 springfox(Swagger 2.x)的现代替代方案,完全支持 Spring Boot 3.x…...
Java 实用时间工具类:DateUtils 与 DurationFormatUtils
前言 在 Java 项目中,处理日期时间相关的操作极为常见。Apache Commons Lang 提供了两个非常实用的时间工具类:DateUtils 和 DurationFormatUtils,它们分别负责简化日期处理和格式化时间间隔,帮助开发者更高效地进行时间操作。 一…...
Unity3D仿星露谷物语开发40之割草动画
1、目标 当Player选择Scythe后,鼠标悬浮在草上,会显示绿色光标。鼠标左击,会触发割草的动画。 2、优化Settings.cs脚本 添加以下两行代码: // Reaping(收割) public const int maxCollidersToTestPerRe…...
量化交易之数学与统计学基础2.4——线性代数与矩阵运算 | 矩阵分解
量化交易之数学与统计学基础2.4——线性代数与矩阵运算 | 矩阵分解 第二部分:线性代数与矩阵运算 第4节:矩阵分解:奇异值分解(SVD)在数据压缩和风险分解的应用 一、奇异值分解(SVD)基础…...
ES使用之查询方式
文章目录 ES中的数据查询返回字段含义track_total_hits 精准匹配(term)单值匹配多值匹配 全文检索(match)range查询高级查询布尔查询 ES中的数据查询 返回字段含义 track_total_hits track_total_hits是 Elasticsearch 中用于 控制匹配文档总数统计行为 的关键参数。就算…...
力扣-数组-41缺失的第一个正数
思路 关键有两点 原地哈希 把1-len的数分别映射到下标为0 - len-1的地方中 交换后,接着查看下标i被交换过来的数,直到他到了该到的位置或者超出范围 使用while,把不满足映射关系的点一直交换,直到下标指向的位置符合要求 代…...
Nginx — http、server、location模块下配置相同策略优先级问题
一、配置优先级简述 在 Nginx 中,http、server、location 模块下配置相同策略时是存在优先级的,一般遵循 “范围越小,优先级越高” 的原则,下面为你详细介绍: 1. 配置继承关系 http 块:作为全局配置块&…...
管家婆易指开单如何设置零售开单
一,零售设置 1,登录管理员账号-基本信息--职员信息-新建职员及其属于哪个门店。 2,系统维护-系统管理-用户配置-系统配置-切换为“触摸屏模式或者普通零售模式” 3,用户及权限设置-给该员工开通零售及开单等相关的权限 4ÿ…...
深入浅出循环神经网络(RNN):原理、应用与实战
1、引言 在深度学习领域,循环神经网络(Recurrent Neural Network, RNN)是一种专门用于处理**序列数据**的神经网络架构。与传统的前馈神经网络不同,RNN 具有**记忆能力**,能够捕捉数据中的时间依赖性,广泛应…...
【Java】打印运行环境中某个类引用的jar版本路径
背景 正式环境出现jar版本不匹配问题,不知道正式环境用的哪个jar版本。通过一下可以打印出类调用的jar // 获取 POIFSFileSystem 类的加载器并打印其来源路径 ClassLoader classloaderPOIFS org.apache.poi.poifs.filesystem.POIFSFileSystem.class.getClassLoade…...
【效率提升】Vibe Coding时代如何正确使用输入法:自定义短语实现Prompt快捷输入
AI时代的效率神器:用搜狗拼音自定义短语实现Prompt快捷输入 在日益依赖AI工具的今天,我们经常需要输入各种复杂的prompt来指导AI完成特定任务。有些同学完全忽视了这一层工作的意义,实际上不同质量的prompt对模型的表现影响是巨大的。&#…...
C# 类的基本概念(从类的内部访问成员和从类的外部访问成员)
本章内容: 类的概述 程序和类:一个简单的示例 声明类 类成员 创建变量和类的实例 为数据分配内存 实例成员 访问修饰符 从类的内部访问成员 从类的外部访问成员 综合应用 从类的内部访问成员 如前所述,类的成员仅用其他类成员的名称就可以访…...
端到端观测分析:从前端负载均衡到后端服务
前言 我们在做系统运维保障的时候,关注从前端负载均衡到后端服务的流量情况是很有必要的,可以了解每个后端服务实例接收的流量大小,这有助于确定资源分配是否合理,能够帮助找出后端服务中的性能瓶颈。同时,当系统出现…...
Axure疑难杂症:全局变量跨页面赋值、中继器交互(玩转全局变量)
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:全局变量高级交互 主要内容:数据跨页面传递、赋值、中继器交互 应用场景:页面间值的传递、赋值 案例展示:…...
css 数字从0开始增加的动画效果
项目场景: 提示:这里简述项目相关背景: 在有些时候比如在做C端项目的时候,页面一般需要一些炫酷效果,比如数字会从小值自动加到数据返回的值 css 数字从0开始增加的动画效果 分析: 提示:这里填…...
【MongoDB篇】MongoDB的索引操作!
目录 引言第一节:天生的“索引小能手”——_id 索引 🆔第二节:自己动手,丰衣足食——创建索引 🔑🛠️第三节:索引的“类型”——因“材”施“索”!🌳🔑第四节…...
写劳动节前的 跨系统 文件传输
功能说明: 协议隐身:流量伪装为HTTPS图片传输 动态混淆:每个数据包添加随机填充 军用级擦除:临时文件三次覆写清除 抗分析:随机传输时间间隔和端口跳跃 隐蔽通道:ALTSHIFTC触发隐藏控制台 网络架构建…...
腾讯元宝桌面客户端:基于Tauri的开源技术解析
2025年3月,腾讯元宝宣布上线电脑客户端版本,支持Windows和macOS系统。作为腾讯旗下的AI助手产品,腾讯元宝桌面端采用了Tauri而非传统的Electron作为其跨平台开发框架,这一技术选择体现了腾讯对应用性能、安全性和用户体验的重视。本文将依据腾讯元宝桌面客户端的用户规则中…...
重塑驾乘体验!哈曼Ready系列引爆「人车交互革命」
AI定义汽车趋势下,AI加速赋能整车辅助驾驶、智能座舱、智能底盘等各域。 以智能座舱为例,AI大模型的快速应用与迭代,推动智能座舱加速迈入“多模交互”阶段,融合视觉、听觉、触觉等感知技术,智能座舱向着终极形态演进…...
第二章-科学计算库NumPy
第二章-科学计算库NumPy Numpy 作为高性能科学计算和数据分析的基础包,是其他重要数据分析工具的基础, 掌握 NumPy 的功能及其用法, 将有助于后续其他数据分析工具的学习. 2.1 认识 NumPy 数组对象 NumPy 中最重要的一个特点就是其 N 维数组对象, 即 ndarray(别名 array) 对象…...
3.2goweb框架GORM
GORM 是 Go 语言中功能强大的 ORM(对象关系映射)框架,支持 MySQL、PostgreSQL、SQLite、SQL Server 等主流数据库。以下是 GORM 的核心概念和用法详解: 一、基础入门 1. 安装 go get -u gorm.io/gorm go get -u gorm.io…...
KUKA机器人不同的用户权限详细介绍
对于KUKA机器人,主菜单里有一个“用户组”的登录,不同的用户组对应不同的权限。 一、KUKA示教器正常开机后显示以下界面,对于8.5及以上的系统,增加了快捷登录用户组的符号 ,直接点击即可打开。在 smartHMI 上&…...
AI对IT行业的重塑:挑战与机遇并存的技术革命
一、必要性:AI成为IT行业的基础设施 在云计算、大数据和物联网构成的数字生态中,AI技术已成为IT行业的"水电煤"。以微软Azure为例,其AI云服务支撑着全球超过85%的《财富》500强企业,通过机器学习模型自动优化服务器集群…...
利用IEEE异常机制优化Fortran浮点数计算
利用IEEE异常机制优化Fortran浮点数计算 在Fortran程序中,IEEE浮点异常机制可以帮助你检测和优化浮点数计算,提高数值稳定性和程序健壮性。以下是几种利用IEEE异常机制优化浮点数计算的方法: 1. 启用和检测IEEE异常 现代Fortran࿰…...
构建网页版IPFS去中心化网盘
前言:我把它命名为无限网盘 Unlimited network disks(ULND),可以实现简单的去中心化存储,其实实现起来并不难,还是依靠强大的IPFS,跟着我一步一步做就可以了。 第一步:准备开发环境…...
【solidity基础】一文说清楚合约函数的大小事
在 Solidity 里,函数是合约的关键构成部分,用于执行特定任务或操作的代码块,可以包含逻辑、访问状态变量、进行计算,并且可以接受参数和返回值。 但是solidity 的函数与其他语言不太一样,经常会有同学搞混,这里开一篇文章完整介绍一下 solidity 函数的用法。 1. 函数定…...
用Python构建自动驾驶传感器融合算法:从理论到实践
用Python构建自动驾驶传感器融合算法:从理论到实践 随着自动驾驶技术的飞速发展,传感器在自动驾驶系统中的作用愈发重要。传感器不仅是车辆感知外部环境的“眼睛”,它们提供的信息也是自动驾驶决策系统的基础。然而,单一传感器的感知能力是有限的。为了提升自动驾驶系统的…...