list的使用,及部分功能的模拟实现(C++)
目录(文章中"节点"和"结点"是同一个意思)
1. list的介绍及使用
1.1 list的介绍
1.2 list的使用
1.2.1 list的构造
1.2.2 list iterator的使用
1.2.3 list capacity
1.2.4 list element access
1.2.5 list modifiers
1.2.6 list的迭代器失效
2. list的模拟实现
2.1 list_node结点
2.2 list_iterator迭代器
2.2.1 运算符重载!=
2.2.2 运算符重载==
2.2.3 运算符重载前置++
2.2.4 运算符重载后置++
2.2.5 运算符重载前置--
2.2.6 运算符重载后置--
2.2.7 运算符重载*
2.2.8 运算符重载->
2.3 list类
2.3.1 构造函数
2.3.1.1默认构造函数list
2.3.1.2 拷贝构造
2.3.1.3 list(std::initializer_list lt)
2.3.2 析构函数
2.3.3 赋值运算符重载
2.3.4 front和back
2.3.5 size和begin和end
2.3.6 insert插入和erase删除
2.3.6.1 insert插入
2.3.6.2 erase删除
2.3.7 头插push_front,头删pop_front,尾插push_back,尾删pop_back
2.4 整体代码
1. list的介绍及使用
1.1 list的介绍
std::list是 C++ 标准模板库(STL)中的一个容器类,底层实现为双向链表,适用于需要频繁插入和删除操作的场景。
1.2 list的使用
以下为list中一些常见的重要接口。
1.2.1 list的构造
构造函数( (constructor)) | 接口说明 |
list (size_type n, const value_type& val = value_type()) | 构造的list中包含n个值为val的元素 |
list() | 构造空的list |
list (const list& x) | 拷贝构造函数 |
list (InputIterator first, InputIterator last) | 用[first, last)区间中的元素构造 list |
使用演示:
void test1() {list<int> l1(10, 5);list<int> l2;list<int> l3(l1);list<int> l4(l1.begin(),l1.end());for (auto& e : l1){cout << e << " ";}cout << endl;for (auto& e : l2){cout << e << " ";}cout << endl;for (auto& e : l3){cout << e << " ";}cout << endl; for (auto& e : l4){cout << e << " ";}cout << endl; }
结果:
1.2.2 list iterator的使用
这里可以暂时将迭代器理解成一个指针,该指针指向list中的某个节点。(其实底层实现时,迭代器是一个封装的对象)
函数声明 | 接口说明 |
begin + end | 返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器 |
rbegin + rend | 返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位 置的reverse_iterator,即begin位置 |
1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动
使用演示:
void test2() {list<int> l;l.push_back(1);l.push_back(2);l.push_back(3);l.push_back(4);l.push_back(5);list<int>::reverse_iterator rit = l.rbegin();while (rit != l.rend()){cout << *rit << " ";rit++;}cout << endl;list<int>::iterator it = l.begin();while (it != l.end()){cout << *it << " ";it++;}cout << endl; }
结果:
1.2.3 list capacity
函数声明 | 接口说明 |
empty | 检测list是否为空,是返回true,否则返回false |
size | 返回list中有效节点的个数 |
使用演示:
void test3() {list<int> l;l.push_back(1);l.push_back(2);l.push_back(3);l.push_back(4);l.push_back(5);if(!l.empty()){cout << "该链表非空" << endl;}cout << "有效节点个数:" << l.size() << endl; }
结果:
1.2.4 list element access
函数声明 | 接口说明 |
front | 返回list的第一个节点中值的引用 |
back | 返回list的最后一个节点中值的引用 |
使用演示:
void test4() {list<int> l;l.push_back(1);l.push_back(2);l.push_back(3);l.push_back(4);l.push_back(5);cout << l.front() << endl;cout << l.back() << endl; }
结果:
1.2.5 list modifiers
函数声明 | 接口说明 |
push_front | 在list首元素前插入值为val的元素 |
pop_front | 删除list中第一个元素 |
push_back | 在list尾部插入值为val的元素 |
pop_back | 删除list中最后一个元素 |
insert | 在list position 位置中插入值为val的元素 |
erase | 删除list position位置的元素 |
swap | 交换两个list中的元素 |
clear | 清空list中的有效元素 |
使用演示:
push_front和pop_front使用:
void test5() {list<int> l;l.push_back(1);l.push_back(2);l.push_back(3);l.push_back(4);l.push_back(5);for (auto& e : l){cout << e << " ";}cout << endl;l.push_front(10);cout << "头插后:";for (auto& e : l){cout << e << " ";}cout << endl;l.pop_front();cout << "头删后:";for (auto& e : l){cout << e << " ";}cout << endl; }
结果:
push_back和pop_back:
void test6() {list<int> l;l.push_back(1);l.push_back(2);l.push_back(3);l.push_back(4);l.push_back(5);for (auto& e : l){cout << e << " ";}cout << endl;l.push_back(6);cout << "尾插后:";for (auto& e : l){cout << e << " ";}cout << endl;l.pop_back();cout << "尾删后:";for (auto& e : l){cout << e << " ";}cout << endl; }
结果:
insert和erase:
void test7() {list<int> l;l.push_back(1);l.push_back(2);l.push_back(3);l.push_back(4);l.push_back(5);for (auto& e : l){cout << e << " ";}cout << endl;l.insert(++l.begin(), 30);cout << "插入后:";for (auto& e : l){cout << e << " ";}cout << endl;l.erase(--l.end());cout << "删除后:";for (auto& e : l){cout << e << " ";}cout << endl; }
结果:
swap:
void test8() {list<int> l1;l1.push_back(1);l1.push_back(2);l1.push_back(3);l1.push_back(4);l1.push_back(5);list<int> l2(5, 5);cout << "交换前" << endl;cout << "l1:";for (auto& e : l1){cout << e << " ";}cout << endl;cout << "l2:";for (auto& e : l2){cout << e << " ";}cout << endl;cout << "交换后" << endl;l1.swap(l2);cout << "l1:";for (auto& e : l1){cout << e << " ";}cout << endl;cout << "l2:";for (auto& e : l2){cout << e << " ";}cout << endl; }
结果:
clear:
void test9() {list<int> l1;l1.push_back(1);l1.push_back(2);l1.push_back(3);l1.push_back(4);l1.push_back(5);cout << "清空前" << endl;cout << "有效元素个数:" << l1.size() << endl;for (auto& e : l1){cout << e << " ";}cout << endl;l1.clear();cout << "清空后" << endl;cout << "有效元素个数:" << l1.size() << endl;for (auto& e : l1){cout << e << " ";}cout << endl; }
结果:
1.2.6 list的迭代器失效
小编前面文章里面“vector迭代器失效”,提到只要使用erase或者insert之后迭代器就直接失效,但是对于list有所不同,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。
举例(删除所有结点):
void test10() {int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array + sizeof(array) / sizeof(array[0]));auto it = l.begin();while (it != l.end()){// erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给其赋值l.erase(it);++it;} }
结果:
可以看到这里报段错误,迭代器失效了。
改进后:
void test10() {int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array + sizeof(array) / sizeof(array[0]));auto it = l.begin();while (it != l.end()){it=l.erase(it);} }
因为erase函数删除后,会返回删除结点的下一个节点迭代器,it接收返回值,相当于更新了迭代器。
2. list的模拟实现
这里利用双向带头链表实现,因为链表的物理空间并不是连续的,所以这里的迭代器不能使用指针,这里对迭代器进行了封装,实现一个对象。还有这里为了和原本库里list区分,将自己写的list封装在命名空间里(作者的是iu)
2.1 list_node结点
template<class T>
struct list_node
{list_node<T>* _prev;list_node<T>* _next;T _value;list_node(const T& x = T()):_prev(nullptr),_next(nullptr),_value(x){}
};
双向带头链表,所以成员有前驱结点,和后继结点,和元素对象。
2.2 list_iterator迭代器
template<class T,class REF,class PTR>
struct list_iterator
{typedef list_node<T> Node;typedef list_iterator<T, REF, PTR> Self;Node* _node;list_iterator(Node* node):_node(node){}};
这里模版为什么会有REF和PTR?其实是解决,范围for迭代器访问时,会有const修饰的对象,如果直接确定的写,只有普通对象可以,所以这里多给两个参数模版,让编译器自己去判断是const修饰的对象,还是普通对象。
2.2.1 运算符重载!=
bool operator!=(const Self& it)
{return _node!=it._node;
}
2.2.2 运算符重载==
bool operator==(const Self& it)
{return _node == it._node;
}
2.2.3 运算符重载前置++
Self& operator++()
{_node = _node->_next;return *this;
}
结点的指向直接向后移动一位。
2.2.4 运算符重载后置++
Self operator++(int)
{Self tmp(*this);_node = _node->_next;return tmp;
}
创建一个临时对象,节点的指向向后移动一位,返回临时对象。
2.2.5 运算符重载前置--
Self& operator--()
{_node = _node->_prev;return *this;
}
结点的指向直接向前移动一位。
2.2.6 运算符重载后置--
Self operator++(int)
{Self tmp(*this);_node = _node->_next;return tmp;
}
创建一个临时对象,节点的指向向前移动一位,返回临时对象。
2.2.7 运算符重载*
REF operator*()
{return _node->_value;
}
解引用,就是返回对象的值。
2.2.8 运算符重载->
PTR operator->()
{return &_node->_value;
}
这里为什么是取值的地址?通过下面的例子来讲解:
void test2() {struct A{A(int a = 0,int b=0):_a(a),_b(b){}int _a;int _b;};iu::list<A>l2;l2.push_back({1,1});l2.push_back({2,2});l2.push_back({3,3});l2.push_back({4,4});iu::list<A>::iterator it = l2.begin();while (it != l2.end()){cout << (*it)._a << ":" << it->_b << endl;it++;} }
这里可以利用解引用在去访问,A类中的成员,这是一种访问方式;而这个it->b是如何访问的?前面实现的是返回A的地址,拿到A对象的地址和成员_b之间也没有运算符,那有怎么样才能访问到_b呢?其实这里省略了一个->,这里其实应该是it->->_b,所以先拿到A对象的地址,再利用结构体->这种方式。解引用访问里面的成员。
结果:
2.3 list类
template<class T>class list{typedef list_node<T> Node;public:typedef list_iterator<T,T&,T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;private:Node* _head;size_t _size;};
}
成员有头结点,和元素个数。
2.3.1 构造函数
2.3.1.1默认构造函数list
void empty_init()
{_head = new Node;_head->_prev = _head;_head->_next = _head;_size = 0;
}list()
{empty_init();
}
这里利用empty_init函数,进行初始化,是为了方便后面几个构造函数,先初始化,再尾插的操作。
2.3.1.2 拷贝构造
list(const list<T>& lt)
{empty_init();for (auto& e : lt){push_back(e);}
}
初始化,再遍历一遍lt,进行尾插依次插入。
2.3.1.3 list(std::initializer_list<T> lt)
list(std::initializer_list<T> lt)
{empty_init();for (auto& e : lt){push_back(e);}
}
和上面同理。
这里举一个例子:
void test8() {iu::list<int>l1 = { 1,2,3,4,5,6,7 };for (auto& e : l1){cout << e << " ";}cout << endl; }
结果:
这个initializer_list<T>类型是一个类似于数组的类型,可以理解成一种类似数组初始化的方式。
2.3.2 析构函数
void clear()
{iterator it = begin();while (it != end()){it = erase(it);}
}~list()
{clear();delete _head;_head = nullptr;
}
先在clear函数里面将数据全部清除,再将头结点释放掉,置为空。
2.3.3 赋值运算符重载
void swap(list<T>& lt)
{std::swap(_head, lt._head);std::swap(_size, lt._size);
}list<T>& operator=(list<T> lt)
{swap(lt);return *this;
}
利用std中的交换函数,将临时对象与this指向的对象进行交换,临时对象出了作用域会自然销毁,也不会影响实参,这样就相当于实现了赋值操作。
2.3.4 front和back
T& front()
{return _head->_next->_value;
}const T& front()const
{return _head->_next->_value;
}
T& back()
{return _head->_prev->_value;
}
const T& back()const
{return _head->_prev->_value;
}
这里利用的是双向带头链表,所以头部front元素就是头结点的下一个,尾结点back就是头结点的前一个。这里还重载了const修饰的对象,当对象元素是不可改变的const时,也可以使用。
2.3.5 size和begin和end
size_t size()
{return _size;
}iterator begin()
{return _head->_next;
}iterator end()
{return _head;
}const_iterator begin() const
{return _head->_next;
}const_iterator end() const
{return _head;
}
size函数,直接返回成员_size大小即可。
begin()返回头结点的下一个结点的迭代器,end()返回最后一个元素的下一个结点的迭代器,所以就是头结点head,这里也是重载了const修饰的对象,当对象元素是不可改变的const时,也可以使用。
2.3.6 insert插入和erase删除
2.3.6.1 insert插入
void insert(iterator pos,const T& x)
{Node* newnode = new Node(x);Node* cur = pos._node;Node* prev = cur->_prev;prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;++_size;
}
首先创建一个新的结点,再进行插入操作,插入时,先找到pos位置的结点,和pos位置的前一个结点,再改变前后指针指向即可,最后_size再加1。
2.3.6.2 erase删除
iterator erase(iterator pos)
{assert(pos != end());Node* del = pos._node;Node* prev = del->_prev;Node* next = del->_next;prev->_next = next;next->_prev = prev;delete del;--_size;return iterator(next);
}
首先找到pos位置的结点,再确定pos前一个结点,和后一个结点的位置,最后改变指针指向,再删除pos位置的节点,_size再减1,最后还要返回删除节点的下一个位置的结点,返回匿名对象即可。
2.3.7 头插push_front,头删pop_front,尾插push_back,尾删pop_back
void push_back(const T& x)
{insert(end(), x);
}
void push_front(const T& x)
{insert(begin(), x);
}
void pop_back()
{erase(--end());
}void pop_front()
{erase(begin());
}
这里直接复用insert和erase函数实现,只是要注意尾结点的位置是end()的前一个位置。
例子:
void test4() {iu::list<int>l1;l1.push_back(1);l1.push_back(2);l1.push_back(3);l1.push_back(4);l1.insert(l1.begin(), 10);l1.insert(l1.begin(), 20);for (auto& e : l1){cout << e << " ";}cout << endl;l1.pop_back();l1.pop_back();l1.pop_front();l1.pop_front();for (auto& e : l1){cout << e << " ";}cout << endl; }
结果:
2.4 整体代码
#include<assert.h>
#include<algorithm>
#include <initializer_list>namespace iu
{template<class T>struct list_node{list_node<T>* _prev;list_node<T>* _next;T _value;list_node(const T& x = T()):_prev(nullptr),_next(nullptr),_value(x){}};template<class T,class REF,class PTR>struct list_iterator{typedef list_node<T> Node;typedef list_iterator<T, REF, PTR> Self;Node* _node;list_iterator(Node* node):_node(node){}bool operator!=(const Self& it){return _node!=it._node;}bool operator==(const Self& it){return _node == it._node;}REF operator*(){return _node->_value;}PTR operator->(){return &_node->_value;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}};template<class T>class list{typedef list_node<T> Node;public:typedef list_iterator<T,T&,T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;void empty_init(){_head = new Node;_head->_prev = _head;_head->_next = _head;_size = 0;}list(){empty_init();}void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}list<T>& operator=(list<T> lt){swap(lt);return *this;}list(std::initializer_list<T> lt){empty_init();for (auto& e : lt){push_back(e);}}list(const list<T>& lt)//拷贝构造{empty_init();for (auto& e : lt){push_back(e);}}~list(){clear();delete _head;_head = nullptr;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}T& front(){return _head->_next->_value;}const T& front()const{return _head->_next->_value;}T& back(){return _head->_prev->_value;}const T& back()const{return _head->_prev->_value;}size_t size(){return _size;}iterator begin(){return _head->_next;}iterator end(){return _head;}const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}void push_back(const T& x){//Node* newnode = new Node(x);//Node* tail = _head->_prev;//newnode->_prev = tail;//tail->_next = newnode;//newnode->_next = _head;//_head->_prev = newnode;insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void insert(iterator pos,const T& x){Node* newnode = new Node(x);Node* cur = pos._node;Node* prev = cur->_prev;prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;++_size;}iterator erase(iterator pos){assert(pos != end());Node* del = pos._node;Node* prev = del->_prev;Node* next = del->_next;prev->_next = next;next->_prev = prev;delete del;--_size;return iterator(next);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}private:Node* _head;size_t _size;};
}
相关文章:
list的使用,及部分功能的模拟实现(C++)
目录(文章中"节点"和"结点"是同一个意思) 1. list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.2.6 list…...
makailio-alias_db模块详解
ALIAS_DB 模块 作者 Daniel-Constantin Mierla micondagmail.com Elena-Ramona Modroiu ramonaasipto.com 编辑 Daniel-Constantin Mierla micondagmail.com 版权 © 2005 Voice Sistem SRL © 2008 asipto.com 目录 管理员指南 概述依赖 2.1 Kamailio 模块 2.2 外…...
【AI】DeepSeek 概念/影响/使用/部署
在大年三十那天,不知道你是否留意到,“deepseek”这个词出现在了各大热搜榜单上。这引起了我的关注,出于学习的兴趣,我深入研究了一番,才有了这篇文章的诞生。 概念 那么,什么是DeepSeek?首先百…...
算法随笔_35: 每日温度
上一篇:算法随笔_34: 最后一个单词的长度-CSDN博客 题目描述如下: 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升…...
人工智能入门课【手写自注意力机制】
原理 自注意力(Self-Attention)是一种强大的机制,广泛应用于自然语言处理、计算机视觉等领域,尤其是在Transformer架构中发挥了关键作用。它的核心思想是让模型能够动态地关注输入序列中不同位置之间的关系,从而更好地…...
记7(激活函数+多层神经网络+梯度下降法及其优化
目录 1、激活函数1.1、sigmoid函数:2端饱和,下面2个函数都要幂运算,运算速度会比较慢1.2、ReLU函数(Rectified Linear Unit,修正线性单元)1.3、PReLU函数(Parameteric Rectified Linear Unit&am…...
Qt u盘自动升级软件
Qt u盘自动升级软件 Chapter1 Qt u盘自动升级软件u盘自动升级软件思路:step1. 获取U盘 判断U盘名字是否正确, 升级文件是否存在。step2. 升级step3. 升级界面 Chapter2 Qt 嵌入式设备应用程序,通过U盘升级的一种思路Chapter3 在开发板上运行的…...
关于低代码技术架构的思考
我们经常会看到很多低代码系统的技术架构图,而且经常看不懂。是因为技术架构图没有画好,还是因为技术不够先进,有时候往往都不是。 比如下图: 一个开发者,看到的视角往往都是技术层面,你给用户讲React18、M…...
如何使用 ChatBox AI 简化本地模型对话操作
部署模型请看上一篇帖子:本地部署DeepSeek教程(Mac版本)-CSDN博客 使用 ChatBox AI 简化本地模型对话操作: 打开 ChatBox AI 官网:Chatbox AI官网:办公学习的AI好助手,全平台AI客户端…...
缩位求和——蓝桥杯
1.题目描述 在电子计算机普及以前,人们经常用一个粗略的方法来验算四则运算是否正确。 比如:248153720248153720 把乘数和被乘数分别逐位求和,如果是多位数再逐位求和,直到是 1 位数,得 24814>145 156 56 而…...
hexo部署到github page时,hexo d后page里面绑定的个人域名消失的问题
Hexo 部署博客到 GitHub page 后,可以在 setting 中的 page 中绑定自己的域名,但是我发现更新博客后绑定的域名消失,恢复原始的 githubio 的域名。 后面搜索发现需要在 repo 里面添加 CNAME 文件,内容为 page 里面绑定的域名&…...
neo4j入门
文章目录 neo4j版本说明部署安装Mac部署docker部署 neo4j web工具使用数据结构图数据库VS关系数据库 neo4j neo4j官网Neo4j是用ava实现的开源NoSQL图数据库。Neo4作为图数据库中的代表产品,已经在众多的行业项目中进行了应用,如:网络管理&am…...
代码随想录——回溯
文章目录 组合组合总数电话号码的字母组合组合总数组合总数Ⅱ分割回文串复原IP地址子集子集Ⅱ非递减子序列去重的实现方法方法 1:**排序 跳过重复元素**方法 2:**使用哈希表或数组记录已使用的数字** 去重的完整示例总结本题代码 全排列全排列Ⅱ重新安排…...
独立游戏RPG回顾:高成本
刚看了某纪录片, 内容是rpg项目的回顾。也是这个以钱为核心话题的系列的最后一集。 对这期特别有代入感,因为主角是曾经的同事,曾经在某天晚上听过其项目组的争论。 对其这些年的起伏特别的能体会。 主角是制作人,在访谈中透露这…...
SQLModel入门
目录 概述快速开始官方教程简单使用样例 概述 SQLModel 是一个 ORM 框架,其基于 SQLAlchemy 和 Pydantic,其中 SQLALchemy 提供底层 ORM 能力,Pydantic 提供类型校验能力,SQLModel 中,一个 SQLModel model 既是一个 S…...
关于MySQL InnoDB存储引擎的一些认识
文章目录 一、存储引擎1.MySQL中执行一条SQL语句的过程是怎样的?1.1 MySQL的存储引擎有哪些?1.2 MyIsam和InnoDB有什么区别? 2.MySQL表的结构是什么?2.1 行结构是什么样呢?2.1.1 NULL列表?2.1.2 char和varc…...
【学习笔记】深度学习网络-正则化方法
作者选择了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰写的《Deep Learning》(人工智能领域的经典教程,深度学习领域研究生必读教材),开始深度学习领域学习,深入全面的理解深度学习的理论知识。 在之前的文章中介绍了深度学习中用…...
NVIDIA (英伟达)的 GPU 产品应用领域
游戏娱乐领域 PC 游戏:NVIDIA 的 GeForce 系列 GPU 是 PC 游戏玩家的首选之一。能实现实时光线追踪、高分辨率渲染等,使游戏画面更加逼真,如《赛博朋克 2077》等支持光线追踪的游戏,在 NVIDIA GPU 的加持下,可呈现出真…...
Docker快速部署高效照片管理系统LibrePhotos搭建私有云相册
文章目录 前言1.关于LibrePhotos2.本地部署LibrePhotos3.LibrePhotos简单使用4. 安装内网穿透5.配置LibrePhotos公网地址6. 配置固定公网地址 前言 想象一下这样的场景:你有一大堆珍贵的回忆照片,但又不想使用各种网盘来管理。怎么办?别担心…...
goframe 多语言国际化解决方案
项目背景 本项目采用基于JSON配置的多语言国际化(i18n)解决方案,支持多种语言的无缝切换和本地化。 目录结构 manifest/ └── i18n/├── zh.json # 简体中文├── zh-tw.json # 繁体中文├── en.json # 英语├…...
mysql如何修改密码
在MySQL中修改密码可以通过多种方式完成,具体取决于你的MySQL版本和你是否有足够的权限。以下是一些常用的方法来修改MySQL用户的密码: 方法1: 使用ALTER USER命令 这是最常用的方法,适用于MySQL 5.7及以上版本。 ALTER USER usernameloca…...
17.2 图形绘制8
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 17.2.10 重绘 先看以下例子: 【例 17.28】【项目:code17-028】绘制填充矩形。 private void button1_Clic…...
Java基础知识总结(三十八)--读取数据
使用Reader体系,读取一个文本文件中的数据。返回 -1 ,标志读到结尾。 import java.io.*; class { public static void main(String[] args) throws IOException { /* 创建可以读取文本文件的流对象,让创建好的流对象和指定的文件相关联。…...
【并查集】
并查集(Disjoint Set Union,DSU)是一种用于处理不相交集合的数据结构,主要支持两种操作:查找(Find)和合并(Union)。它在解决连通性问题、图论问题以及动态连通性等问题时…...
SQL NOW() 函数详解
SQL NOW() 函数详解 引言 在SQL数据库中,NOW() 函数是一个常用的日期和时间函数,用于获取当前的时间戳。本文将详细介绍 NOW() 函数的用法、参数、返回值以及在实际应用中的注意事项。 函数概述 NOW() 函数返回当前的日期和时间,格式为 Y…...
[EAI-023] FAST,机器人动作专用的Tokenizer,提高VLA模型的能力和训练效率
Paper Card 论文标题:FAST: Efficient Action Tokenization for Vision-Language-Action Models 论文作者:Karl Pertsch, Kyle Stachowicz, Brian Ichter, Danny Driess, Suraj Nair, Quan Vuong, Oier Mees, Chelsea Finn, Sergey Levine 论文链接&…...
Rust 条件语句
Rust 条件语句 在编程语言中,条件语句是进行决策和实现分支逻辑的关键。Rust 语言作为一门系统编程语言,其条件语句的使用同样至关重要。本文将详细介绍 Rust 中的条件语句,包括其基本用法、常见场景以及如何避免常见错误。 基本用法 Rust…...
Windows 上安装 PostgreSQL
Windows 上安装 PostgreSQL PostgreSQL 是一款功能强大的开源对象-关系型数据库系统,它具有出色的扩展性和稳定性。本文将详细介绍在 Windows 操作系统上安装 PostgreSQL 的步骤和注意事项。 1. 准备工作 在开始安装 PostgreSQL 之前,请确保您的计算机满足以下要求: 操作…...
UE 5.3 C++ 对垃圾回收的初步认识
一.UObject的创建 UObject 不支持构造参数。 所有的C UObject都会在引擎启动的时候初始化,然后引擎会调用其默认构造器。如果没有默认的构造器,那么 UObject 将不会编译。 有修改父类参数的需求,就使用指定带参构造 // Sets default value…...
解码,蓝桥杯2020G
a2b 解码后:aab #include<iostream> using namespace std; typedef struct Node {char data;int size;Node* next; }Node,*Linklist; char* scan(char str[],int size) {int i 0;Linklist head new Node;Linklist rear head;while (i<size-1) {Lin…...
【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(一)
✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨ 文章所属专栏:贪心算法篇–CSDN博客 文章目录 一.贪心算法1.什么是贪心算法2.贪心算法的特点 二.例题1.柠…...
Python3 + Qt5:实现AJAX异步更新UI
使用 Python 和 Qt5 开发时异步加载数据的方法 在开发使用 Python 和 Qt5 的应用程序时,为了避免在加载数据时界面卡顿,可以采用异步加载的方式。以下是几种实现异步加载的方法: 1. 使用多线程(QThread) 通过将数据…...
Windows系统中Docker可视化工具对比分析,Docker Desktop,Portainer,Rancher
Docker可视化工具对比分析,Docker Desktop,Portainer,Rancher Windows系统中Docker可视化工具对比分析1. 工具概览2. Docker Desktop官网链接:主要优点:主要缺点:版本更新频率: 3. Portainer官网…...
从ai产品推荐到利用cursor快速掌握一个开源项目再到langchain手搓一个Text2Sql agent
目录 0. 经验分享:产品推荐 1. 经验分享:提示词优化 2. 经验分享:使用cursor 阅读一篇文章 3. 经验分享:使用cursor 阅读一个完全陌生的开源项目 4. 经验分享:手搓一个text2sql agent (使用langchain l…...
curope python安装
目录 curope安装 测试: 报错:libc10.so: cannot open shared object file: No such file or directory 解决方法: curope安装 git clone : GitHub - Junyi42/croco at bd6f4e07d5c4f13ae5388efc052dadf142aff754 cd models/curope/ python setup.py build_ext --inplac…...
低代码产品插件功能一览
下图是统计的目前市面上流行的低代码、零代码产品的插件功能。 产品名称 产品类型 官方插件数量 支持拓展 官方插件功能 宜搭 零代码 3 暂不支持 云打印、CAD看图、打印表单详情 微搭 低代码 1 暂不支持 小程序 明道云 低代码 2 支持 视图、工作流节点 简道…...
流浪 Linux: 外置 USB SSD 安装 ArchLinux
注: ArchLinux 系统为滚动更新, 变化很快, 所以本文中的安装方法可能很快就过时了, 仅供参考. 实际安装时建议去阅读官方文档. 最近, 突然 (也没有那么突然) 有了一大堆 PC: 4 个笔记本, 2 个台式主机 (M-ATX 主板), 1 个小主机 (迷你主机). 嗯, 多到用不过来. 但是, 窝又不能…...
开启 AI 学习之旅:从入门到精通
最近 AI 真的超火,不管是工作还是生活里,到处都能看到它的身影。好多小伙伴都跑来问我,到底该怎么学 AI 呢?今天我就把自己学习 AI 的经验和心得分享出来,希望能帮到想踏入 AI 领域的朋友们! 一、学习内容有哪些 (一)编程语言 Python 绝对是首选!它在 AI 领域的生态…...
笔记:使用ST-LINK烧录STM32程序怎么样最方便?
一般板子在插件上, 8脚 3.3V;9脚 CLK;10脚 DIO;4脚GND ST_Link 19脚 3.3V;9脚 CLK;7脚 DIO;20脚 GND 烧录软件:ST-LINK Utility,Keil_5; ST_Link 接口针脚定义: 按定义连接ST_Link与电路板; 打开STM32 ST-LINK Uti…...
开发环境搭建-4:WSL 配置 docker 运行环境
在 WSL 环境中构建:WSL2 (2.3.26.0) Oracle Linux 8.7 官方镜像 基本概念说明 容器技术 利用 Linux 系统的 文件系统(UnionFS)、命名空间(namespace)、权限管理(cgroup),虚拟出一…...
925.长按键入
目录 一、题目二、思路三、解法四、收获 一、题目 你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。 你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字&am…...
【数据采集】案例01:基于Scrapy采集豆瓣电影Top250的详细数据
基于Scrapy采集豆瓣电影Top250的详细数据 Scrapy 官方文档:https://docs.scrapy.org/en/latest/豆瓣电影Top250官网:https://movie.douban.com/top250写在前面 实验目的:基于Scrapy框架采集豆瓣电影Top250的详细数据。 电脑系统:Windows 使用软件:PyCharm、Navicat Python…...
doris:主键模型的导入更新
这篇文档主要介绍 Doris 主键模型基于导入的更新。 整行更新 使用 Doris 支持的 Stream Load、Broker Load、Routine Load、Insert Into 等导入方式,向主键模型(Unique 模型)导入数据时,如果没有相应主键的数据行,…...
日志2025.2.1
日志2025.2.1 1.做了敌人状态机 public class EnermyStateMachine { public EnermyState currentState { get; private set; } public void InitializeState(EnermyState startState) { currentState startState; currentState.Enter(); } public void Change…...
RK3568使用QT操作LED灯
文章目录 一、QT中操作硬件设备思路Linux 中的设备文件操作硬件设备的思路1. 打开设备文件2. 写入数据到设备3. 从设备读取数据4. 设备控制5. 异常处理在 Qt 中操作设备的典型步骤实际应用中的例子:控制 LED总结二、QT实战操作LED灯设备1. `mainwindow.h` 头文件2. `mainwindo…...
Rank-analysis-1.2——一款基于LCU API的排位分析工具,大四学生独立开发
LOL Rank Record Analysis:一款基于LCU API的排位分析工具,大四学生独立开发! 大家好!我是河南科技学院的大四学生,今天给大家分享一个我自己开发的软件——LOL Rank Record Analysis。这是一个基于 Riot 提供的 LCU …...
关于系统重构实践的一些思考与总结
文章目录 一、前言二、系统重构的范式1.明确目标和背景2.兼容屏蔽对上层的影响3.设计灰度迁移方案3.1 灰度策略3.2 灰度过程设计3.2.1 case1 业务逻辑变更3.2.2 case2 底层数据变更(数据平滑迁移)3.2.3 case3 在途新旧流程兼容3.2.4 case4 接口变更3.2.5…...
代码随想录-训练营-day17
235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode) /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/class S…...
C++,STL,【目录篇】
文章目录 一、简介二、内容提纲第一部分:STL 概述第二部分:STL 容器第三部分:STL 迭代器第四部分:STL 算法第五部分:STL 函数对象第六部分:STL 高级主题第七部分:STL 实战应用 三、写作风格四、…...
《数据可视化新高度:Graphy的AI协作变革》
在数据洪流奔涌的时代,企业面临的挑战不再仅仅是数据的收集,更在于如何高效地将数据转化为洞察,助力决策。Graphy作为一款前沿的数据可视化工具,凭借AI赋能的团队协作功能,为企业打开了数据协作新局面,重新…...