邢台做网站建设优化制作公司金信/搜索引擎优化趋势
绪论
拼着一切代价,奔你的前程。 ——巴尔扎克;本章主要围绕vector和list的使用,以及容器底层迭代器失效问题,同时会有对原码的分析和模拟实现其底层类函数。话不多说安全带系好,发车啦(建议电脑观看)。
附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要
1.Vector
vector 重要成员函数 | 具体有 |
---|---|
构造函数 | vetor() |
析构函数 | ~vector() |
迭代器类函数 | begin()、end()、rbegin()、rend()、… |
容量类函数 | resize()、size()、capacity()、reserve()、… |
元素访问类函数 | operator[]、front()、back()、… |
修改类函数 | push_back()、pop_back()、inser()、erase()、clear()、… |
非成员函数 | swap()、relational operator() |
——————————————
Vector就像一个动态的数组也就是顺序表(有些时候可以想象成常规数组),也就是在写好的类中进行一定的函数操作,其中函数操作也就是上面所写。
1.1构造函数
函数作用 | 函数原型 |
---|---|
rang(迭代器) | template <class InputIterator>vector (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type()); |
default(无参的全缺省的) | explicit vector (const allocator_type& alloc = allocator_type()); |
fill(初始化vector为n个value值) | explicit vector (size_type n, const value_type& val = value_type(),const allocator_type& alloc = allocator_type()); |
copy(拷贝构造) | vector (const vector& x); |
附:其中的const allocator_type& alloc = allocator_type())为空间配置器,这里提供了可以修改的缺省值,当你可以修改使用自己的内存池,基本不用修改STL内部提供的内存池 |
//初始化vector的方法
vector<int> v;//缺省
vector<int> v1(10,0);//初始化0个10
vector<int> v2(v1.begin(),v1.end());//迭代器从begin到end初始化
vector<int> v3(v2);//拷贝构造
1.2析构函数
在使用中不用去管因为其会自动执行释放构造函数所申请的空间
1.3迭代器类函数
知识点:
1.3.1begin()、end()、rbegin()、rend()
此处begin、end和string中的差不多用来指向结构中的数据,begin指向vector的首元素(类似于数组的首元素)、end指向的是数组最后一个元素的下一个位置,相反的rbegin指向的是数组的最后一个元素,而rend指向的是第一个元素的前一个位置
其中可以发现begin指向vector内的数据,而end则不会指向vector内
练习使用:
vector<int> v(10, 1);v.push_back(2);vector<int>::iterator it = v.begin();//指向vector首元素的1while (it != v.end()){cout << *it << ' ';it++;}//正向打印出所有元素:1 1 1 1 1 1 1 1 1 1 2 类似于指针cout << endl;vector<int>::reverse_iterator rit = v.rbegin();while (rit != v.rend()){cout << *rit << ' ';rit++;//注意此处仍然是++而不是--}//反向的打印出所有元素:2 1 1 1 1 1 1 1 1 1 1 类似于指针
附:cbegin、cend、crbeing、crend 是针对于const类型的,用法一样就不展开讲了。
1.4容量类函数
知识点:
1.4.1size()
函数原型:size_type size() const;
功能:查看vector中有几个元素。
vector<int> v(10,1);
v.size();//返回10
1.4.2capacity()
函数原型:size_type capacity() const;
功能:查看vector的capacity。
vector<int> v(10,1);
v.capacity();//在VS2019IDE环境下每次扩容1.5倍 1 ~ 2 ~ 3 ~ 6 ~ 9 ~ 13 ....
1.4.3reserve()
函数原型:void reserve (size_type n);
功能:设置vector的capacity,可提前把capacity设置好避免不断动态扩容的消耗
1.4.4resize()
函数原型:void resize (size_type n, value_type val = value_type());
改变vector的size(size决定了vector容器中的元素个数)
一般来说capacity申请扩展后都不会轻易的缩回
1.4.5empty()
函数原型:bool empty() const;
功能:查看vector内是否有数据,若返回true表示size == 0,否则放回false;
1.4.6shrink_to_fit()
函数原型:void shrink_to_fit();
功能:把capacity缩小到size大小(这条函数不一定执行最终是否执行还得看编译器他是无约束力的(non-binding))
1.5元素访问类函数
知识点:
1.5.1operator[]
函数原型 |
---|
reference operator[] (size_type n); |
const_reference operator[] (size_type n) const; |
功能:像数组一样来访问vector中的元素
如:第一个元素v[0]
…
1.5.2at()
函数原型 |
---|
reference at (size_type n); |
const_reference at (size_type n) const; |
功能:访问vector中的元素,但一般来说更多的用operator[]
如:v.at(0);
访问第一个元素
1.5.3front()、back()
front函数原型 | back函数原型 |
---|---|
reference front(); | reference back(); |
const_reference front() const | reference back(); |
front的功能:找到vector中第一个元素并返回
如:vector<int> v(10,1); v.fornt();//指向向首元素1
back的功能:同理就是找到vector的最后一个元素
如:vector<int> v(10,1); v.back();//指向向最后一个元素1
写到这我觉得没必要再写了(有点浪费时间),对于这些函数可以自行查资料,里面有解释以及函数原型!c++官网,下面我将只写函数的用处,但仍然会把一些细节给写出来!
1.6修改类函数
作用 | 具体函数 |
---|---|
尾插 | push_back() |
尾删 | pop_back() |
清除数据 | clear() |
将新的内容覆盖老的内容 | assign() |
在某个位置删除数据 | erase() |
在某处插入数据 | insert() |
交换(直接交换两个对象所指向的地址) | swap() |
附:对于容器中我们若想在指定位置插入的话其实他并没有find函数来找到所对应的任意位置,对此在c++库中的算法库中其实有一个通用的find()查找函数
函数原型为:
template <class InputIterator, class T>
InputIterator find (InputIterator first, InputIterator last, const T& val);
用法如下:
vector<int> v;//在其中存储着1 2 3 4 5 6 7 find(v.begin(),v.end(),3);//传进迭代器区间,在其中找3,最后返回对应迭代器
这样就能找到容器中的数据并且进行一定的操作。
非成员函数 |
---|
vector比较重载函数:relational operators |
交换函数(用处是当两个是vector要进行交换时,去调用vector修改类中的swap,他是std交换函数的重载类):swap() |
对于vector来说,还有个比较重要的点:
vector迭代器失效问题
在vector使用中可能会出现两种迭代器失效的情况:
- 当插入数据后的迭代器失效问题:因为在插入数据的情况下,有可能会发生异地扩容,当发生异地时就会导致原本迭代器所指向的位置为一个野指针也就是所说的迭代器失效,所以我们要注意的是迭代器在插入数据后要给迭代器重新赋值,并且在模拟实现插入函数中我们可能会扩容此处也要记得防止迭代器失效而记录迭代器位置,并作出一定的改变。
iterator insert(iterator pos, const T& x){assert(pos <= _finish);assert(pos >= _start);if (_finish == _endofstorage){size_t n = pos - _start;//记录相对位置防止迭代器在扩容后失效reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + n;}iterator it = _finish;while (it > pos) {*it = *(it - 1);it--;}*it = x;_finish++;return _start;}
- 当删除数据时我们要注意的是,他可能也会有迭代器失效的问题,因为在VS2019IDE下规定当一个迭代器所指向的位置被删除后,该迭代器就已经失效了,我们不能再次的去使用若使用就会报错,而在CentOs7 g++下迭代器会指向物理下的下一个位置(如:1234 删除2后3覆盖了2的位置迭代器就会指向4),此处解决的方法为:更新迭代器让它接收erase的返回值,在c++中规定了erase删除后返回迭代器指向被删除数据的下一个位置,这样才能正确的删除数据, 如:
it = erase(it)//删除后需要接收返回的迭代器
。
vector深浅拷贝问题
当有异地扩容的时候,我们需要去将数据进行拷贝,此处如果是内置类型的话直接进行拷贝然后释放就行了,而对于像string类这种有深浅拷贝问题的就需要注意,我们若用memcpy直接进行的拷贝就会出深浅拷贝问题,对此我们在reserve扩容函数中就需要注意改变写法具体如下。
void reserve(size_t n){if (n > capacity()){T* tmp = new T[n];size_t sz = size();if (_start) {//memcpy(tmp, _start, sz * sizeof(T)); 此处对于自定义类型来说是一个浅拷贝了for(size_t i = 0; i < size();i++){tmp[i] = _start[i];//逐个元素的进行赋值操作就能避免}delete[] _start;}_start = tmp;_finish = _start + sz;//这里不用size()因为这样会导致为nullptr , _endofstorage = _start + n;}}
vector反向迭代器的实现
对于vector反向迭代器来说,我们不能像正向一样的直接用一个指针指向start,他们需要从后往前来走(也就表示当reverse_iterartor ++ 时并不是往前走的而是往后的),这样我们就需要重新分装一个反向迭代器的类,并且对操作符++、–重载改变其原理。对此在一个类中我们还需要去实现一些其他的操作符,具体如下:
template<class iterator>class reverse_iterator{typedef reverse_iterator<iterator> Self;reverse_iterator(iterator t):it(t){}Self& operator++(){it--;return *this;}Self operator++(int){Self tmp (it);it--;return tmp;}Self& operator--(){it++;return *this;}Self operator--(int){reverse_iterator tmp = it;it++;return tmp;}Self& operator*(){reverse_iterator tmp = it;return *(--tmp);}bool operator!=(const Self& t){return it != t.it;}bool operator==(const Self& t){return it == t.it;}private:iterator it;};
模拟实现Vector:
#pragma once
#include<iostream>
#include<stdio.h>
#include<assert.h>using namespace std;namespace bit
{template<class T>class vector{public:// Vector的迭代器是一个原生指针typedef T* iterator;typedef const T* const_iterator;typedef reverse_iterator<iterator> reverse_iterator;reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}iterator begin() {return _start;}iterator end() {return _finish;}const_iterator cbegin() const{return _start;}const_iterator cend() const{return _finish;}// construct and destroy// //对于直接的构造不做如何处理vector(){}vector(size_t n, const T& value = T()){reserve(n);while (n--) {push_back(value);}}vector(int n, const T& value = T()){reserve(n);while (n--) {push_back(value);}}template<class InputIterator>vector(InputIterator first, InputIterator last){assert(first && last);while(first != last){push_back(*first);first++;}}//现代写法:vector(const vector<T>& v){vector<T> tmp(v.cbegin(),v.cend());swap(tmp);}//传统写法://vector(const vector<T>& v)//{// //开辟一个空间// reserve(v.capacity());// //把数据放进去// for (auto& e : v)// {// push_back(e);// }//}vector<T>& operator=(vector<T> v){swap(v);return *this;}//void operator++(int)//{// swap(v);// return *this;//}~vector(){delete[] _start;_start = _finish = _endofstorage = nullptr;} capacitysize_t size() const{return _finish - _start;}size_t capacity() const{return _endofstorage - _start;}void reserve(size_t n){if (n > capacity()){T* tmp = new T[n];size_t sz = size();if (_start) {//memcpy(tmp, _start, sz * sizeof(T)); 此处对于自定义类型来说是一个浅拷贝了for(size_t i = 0; i < size();i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + sz;//这里不用size()因为这样会导致为nullptr , _endofstorage = _start + n;}}void resize(size_t n, const T& value = T()){if (n < capacity()){_finish = _start + n;}else {reserve(n);while (_finish < _start + n){*_finish = value;++_finish;}}}/access///T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos)const{assert(pos < size());return _start[pos];}/modify/void push_back(const T& x){/* if (_finish == _endofstorage){int cp = capacity() == 0 ? 4 : capacity() * 2;reserve(cp);}*_finish = x;_finish++;*/insert(end(), x);}void pop_back(){_finish--;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);}iterator insert(iterator pos, const T& x){assert(pos <= _finish);assert(pos >= _start);if (_finish == _endofstorage){size_t n = pos - _start;//防止迭代器在扩容后失效reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + n;}iterator it = _finish;while (it > pos) {*it = *(it - 1);it--;}*it = x;_finish++;return _start;}iterator erase(iterator pos){assert(pos < _finish);assert(pos >= _start);iterator it = pos + 1;while (it < _finish){*(it - 1) = *it;it++;}_finish--;return pos;}private://给他们初始值是为了预防iterator _start = nullptr; // 指向数据块的开始iterator _finish = nullptr; // 指向有效数据的尾iterator _endofstorage = nullptr; // 指向存储容量的尾};template<class iterator>class reverse_iterator{typedef reverse_iterator<iterator> Self;reverse_iterator(iterator t):it(t){}Self& operator++(){it--;return *this;}Self operator++(int){Self tmp (it);it--;return tmp;}Self& operator--(){it++;return *this;}Self operator--(int){reverse_iterator tmp = it;it++;return tmp;}Self& operator*(){reverse_iterator tmp = it;return *(--tmp);}bool operator!=(const Self& t){return it != t.it;}bool operator==(const Self& t){return it == t.it;}private:iterator it;};}
2.List
在STL的list其实就是数据结构中的带头双向循环列表(若不清楚的建议看看数据机构基础之链表)
list 重要成员函数 | 具体有 |
---|---|
构造函数 | list() |
析构函数 | ~list() |
迭代器类函数 | begin()、end()、rbegin()、rend()、… |
容量类函数 | size()、empty()、… |
元素访问类函数 | front()、back() |
修改类函数 | push_back()、pop_back()、push_front()、inser()、erase()、clear()、… |
操作类函数 | sort() 、 reverse() 、remove() 、… |
非成员函数 | swap()、relational operator() |
同样的在list中也不会去详细的简述函数(这些都是熟能生巧的多去查文档),会在后面写道一些细节内容以及函数的功能
2.1构造函数、析构函数
构造函数( (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 |
析构函数不用自己调用,其内部主要包括把所借的内存归还给操作系统操作
2.2迭代器类函数
具体函数 | 作用 |
---|---|
begin() | 返回第一个元素的迭代器 |
end() | 返回最后一个元素下一个位置的迭代器 |
rbegin() | 返回第一个元素的reverse_iterator,即end位置 |
rend | 返回最后一个元素下一个位置的reverse_iterator,即begin位置 |
注意点 | 在反向迭代器中++,是表示往前走 而不是往后 ; 同理的-- 则表示往后走 |
2.3容量类函数
具体函数 | 作用 |
---|---|
empty() | 检测list是否为空,是返回true,否则返回false |
size() | 返回list中有效节点的个数 |
2.4元素访问类函数
具体函数 | 作用 |
---|---|
front() | 返回list的第一个节点中值的引用 |
back() | 返回list的最后一个节点中值的引用 |
2.5修改类函数
具体函数 | 作用 |
---|---|
push_back(const value_type& val) | 在list尾部插入值为val的元素 |
pop_back() | 删除list中最后一个元素 |
push_front(const value_type& val) | 在list首元素前插入值为val的元素 |
pop_front() | 删除list中第一个元素 |
iterator inser(iterator position, const value_type& val) | 在pos位置(此处是迭代器)处插入值为val的元素,还能插入一次性n个元素以及用迭代器插入一段数据 |
iterator erase(iterator position) | 删除pos迭代器所指向位置的元素,还能一次性删除一段数据erase (iterator first, iterator last) |
clear() | 清空list中的有效元素 |
swap(list& x)) | 交换两个list中的元素 |
void resize (size_type n, value_type val = value_type()) | 提前初始化n个空间初始值默认为value_type()//整形为0… |
2.5.1list 删除操作时的迭代器失效问题:
list在插入数据时并不会迭代器失效,而在删除时因为当前位置的迭代器所指向的地址空间已经被释放,而形成了迭代器失效。
所以为避免这种情况删除的实现会返回一个迭代器(也就是被删除数据的下一个位置)并且我们需要用接收这个迭代器才能解决失效问题(例:iterator it = l.erase(l.begin()))
通过上面的分析我们能知道当list删除数据后其原本的迭代器会指向被删除的数据的下一个数据,并且返回该位置!对此来实现list的删除:
iterator erase(iterator pos){Node* cur = pos._Node;Node* prev = cur->_Prev;Node* next = cur->_Next;//一开始记录删除数据的下一个位置prev->_Next = next;next->_Prev = prev;_size--;return iterator(next);//返回next}
2.6操作类函数
具体函数 | 作用 |
---|---|
void splice (iterator position, list& x) | 拼接两个list,还能x指定中的i位置的一个元素拼接,或者是用迭代器确定区域(first,last]进行拼接 |
remove(valua) | 删除list中所有等于value值的元素 |
template <class Predicate> remove_if(Predicate pred) | 删除所有满足pred仿函数(也可能是函数指针)的元素 |
unique() | 删除重复的值 |
merge(list& x) | 拼接两个list,他有第二个参数为仿函数(或函数指针) |
sort() | 对list中的数据进行排序,默认为升序,可以改变传递仿函数来自定义Compare比较函数(方法) |
reverse() | 逆序把list中的数据倒过来 |
2.7list的实现
#pragma once#include<iostream>
using namespace std;namespace bite
{// List的节点类template<class T>struct ListNode{ListNode(const T& val = T()):_val(val),_Prev(nullptr),_Next(nullptr){}ListNode<T>* _Prev;ListNode<T>* _Next;T _val;};//List的迭代器类template<class T, class Ref, class Ptr>struct ListIterator{typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> Self;public:ListIterator(Node* node = nullptr) :_Node(node){}//ListIterator(const Self& l);T& operator*(){return _Node->_val;}Ptr operator->(){return &_Node->_val;}Self& operator++(){_Node = _Node->_Next;return *this;}//后置Self operator++(int){Self tmp(*this);//拷贝构造//其中self是类型、*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& l){return _Node != l._Node;}bool operator==(const Self& l){return _Node == l._Node;}Node* _Node;};template<class T, class Ref, class Ptr>struct RIterator{typedef ListNode<T> Node;typedef RIterator<T, Ref, Ptr> Self;public:RIterator(Node* node = nullptr):_Node(node){}//ListIterator(const Self& l);T& operator*(){return _Node->_val;}Ptr operator->(){return &_Node->_val;}Self& operator++(){_Node = _Node->_Prev;return *this;}//后置Self operator++(int){Self tmp(*this);//拷贝构造//其中self是类型、*this是一个具体的对象_Node = _Node->_Prev;return tmp;}//前置Self& operator--(){_Node = _Node->_Next;return *this;}//后置需要一个类型来占位Self& operator--(int){Self tmp(*this);_Node = _Node->_Next;return tmp;}bool operator!=(const Self& l){return _Node != l._Node;}bool operator==(const Self& l){return _Node == l._Node;}Node* _Node;};//list类template<class T>class list{public:typedef ListNode<T> Node;typedef ListIterator<T, T&, T*> iterator;//将typedef ListIterator<T, const T&, const T&> const_iterator;typedef RIterator<T, T&, T*> reverse_iterator;//将public:///// List的构造void empty_init(){_Head = new Node;//头节点_Head->_Next = _Head;_Head->_Prev = _Head;}list(){empty_init();}list(int n, const T& value = T()){for(int i = 0; i<n;i++){push_back(value);}}template <class Iterator>list(Iterator first, Iterator last){Iterator it = first;while (it != last){push_back(*it);++it;}}void swap(list<T>& l){std::swap(_Head, l._Head);std::swap(_size, l._size);}list(const list<T>& l){empty_init();for (auto nd : l){push_back(nd);}}list<T>& operator=(list<T> l){swap(l);return *this;}~list(){clear();//将申请的空间返还delete _Head;_Head = nullptr;}///// List Iteratoriterator begin(){//return iterator(_Head->_Next);return _Head->_Next;}iterator end(){//return iterator(_Head);return _Head;}const_iterator begin()const{return _Head->_Next;}const_iterator end()const{return _Head;}reverse_iterator rbegin(){return reverse_iterator(_Head->_Prev);}reverse_iterator rend(){return reverse_iterator(_Head);}// List Capacitysize_t size()const{return _size;}bool empty()const{return _size == 0;} List AccessT& front(){return _Head->_Next->_val;}const T& front()const{return _Head->_Next->_val;}//T& back(){return _Head->_Prev->_val;}//const T& back()const{return _Head->_Prev->_val;}// List Modifyvoid push_back(const T& val){ //Node* tail = _Head->_Prev;//Node* newnode = new Node(val);//tail->_Next = newnode;//newnode->_Prev = tail;//_Head->_Prev = newnode;//newnode->_Next = _Head;//_size++;insert(end(), val); }void pop_back() {/* Node* tail = _Head->_Prev;tail->_Prev->_Next = _Head;_Head->_Prev = tail->_Prev;delete tail;_size--;*/erase(--end()); }void push_front(const T& val) { //Node* head = _Head->_Next;//Node* newnode = new Node(val);//head->_Prev = newnode;//newnode->_Next = head;//_Head->_Next = newnode;//head->_Prev = _Head;//_size++;insert(begin(), val); }void pop_front(){ /* Node* head = _Head->_Next;head->_Next->_Prev = _Head;_Head->_Next = head->_Next;delete head;_size--;*/erase(begin());} 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){Node* cur = pos._Node;Node* newnode = new Node(val);Node* prev = cur->_Prev;prev->_Next = newnode;newnode->_Prev = prev;newnode->_Next = cur;cur->_Prev = newnode;_size++;return iterator(newnode);} 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){Node* cur = pos._Node;Node* prev = cur->_Prev;Node* next = cur->_Next;prev->_Next = next;next->_Prev = prev;_size--;return iterator(next);}void clear(){iterator it = begin();while(it != end()){it = erase(it);}//for(auto it : )_size = 0;}private:Node* _Head;size_t _size;};
}
本章完。预知后事如何,暂听下回分解。
如果有任何问题欢迎讨论哈!
如果觉得这篇文章对你有所帮助的话点点赞吧!
持续更新大量C++细致内容,早关注不迷路。
相关文章:

C++STL---Vector、List所要掌握的基本知识
绪论 拼着一切代价,奔你的前程。 ——巴尔扎克;本章主要围绕vector和list的使用,以及容器底层迭代器失效问题,同时会有对原码的分析和模拟实现其底层类函数。话不多说安全带系好,发车啦(建议电脑…...

使用FastAPI部署Ultralytics YOLOv5模型
YOLO是You Only Look Once(你只看一次)的缩写,它具有识别图像中的物体的非凡能力,在日常应用中会经常被使用。所以在本文中,我们将介绍如何使用FastAPI的集成YOLOv5,这样我们可以将YOLOv5做为API对外提供服务。 Python有几个web框…...

A. Doremy‘s Paint 3
今天第一次打CF,不过鼠鼠被气死了 先说说战况,今天一发没A(赛场上),生活真是无奈,废物女友真是一点用没有 心里也很烦,什么压力都自己扛着。每天想尝试改变什么,又被现实掣肘&…...

深度学习_1 介绍;安装环境
深度学习 学习自李沐老师的课程。笔记主要以总结老师所讲解的内容以及我个人的想法为主,侵删! 课程链接:课程安排 - 动手学深度学习课程 (d2l.ai) 介绍 AI地图: 首先,AI 能对问题处理到什么地步?分为四…...

Python基础入门例程19-NP19 列表的长度(列表)
最近的博文: Python基础入门例程18-NP18 生成数字列表(列表)-CSDN博客 Python基础入门例程17-NP17 生成列表(列表)-CSDN博客 Python基础入门例程16-NP16 发送offer(列表)-CSDN博客 目录 描述 输入描述: 输出描述࿱…...

LeetCode 2558. 从数量最多的堆取走礼物
【LetMeFly】2558.从数量最多的堆取走礼物 力扣题目链接:https://leetcode.cn/problems/take-gifts-from-the-richest-pile/ 给你一个整数数组 gifts ,表示各堆礼物的数量。每一秒,你需要执行以下操作: 选择礼物数量最多的那一…...

【JVM】字节码文件的组成部分
🐌个人主页: 🐌 叶落闲庭 💨我的专栏:💨 c语言 数据结构 javaEE 操作系统 Redis 石可破也,而不可夺坚;丹可磨也,而不可夺赤。 JVM 一、字节码文件的组成部分1.1 iconst_0…...

STM32 TIM(四)编码器接口
STM32 TIM(四)编码器接口 编码器接口简介 Encoder Interface 编码器接口 编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的…...

力扣第56题 合并区间 c++ 贪心
题目 56. 合并区间 中等 相关标签 数组 排序 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 示例…...

php 日期
其中关于周的起止,使用date("N"),确保每周周一为起始,避免周日时出现作为新一周起始的情况 //获取上个月第一天 echo "上个月开始时间:".date(Y-m-01 00:00:00,strtotime(-1 month))."\r\n\r\n"; …...

食物链解读
[NOI2001] 食物链 题目描述 动物王国中有三类动物 A , B , C A,B,C A,B,C,这三类动物的食物链构成了有趣的环形。 A A A 吃 B B B, B B B 吃 C C C, C C C 吃 A A A。 现有 N N N 个动物,以 1 ∼ N 1 \sim N 1∼N 编号。…...

Day10配置文件日志多线程
配置文件 在企业开发过程中,我们习惯把一些需要灵活配置的数据放在一些文本文件中,而不是在Java代码写死 我们把这种存放程序配置信息的文件,统称为配置文件 properties 是一个Map集合(键值对集合),但是我…...

leetcode:1154. 一年中的第几天(python3解法)
难度:简单 给你一个字符串 date ,按 YYYY-MM-DD 格式表示一个 现行公元纪年法 日期。返回该日期是当年的第几天。 示例 1: 输入:date "2019-01-09" 输出:9 解释:给定日期是2019年的第九天。 示例…...

竞赛 深度学习图像修复算法 - opencv python 机器视觉
文章目录 0 前言2 什么是图像内容填充修复3 原理分析3.1 第一步:将图像理解为一个概率分布的样本3.2 补全图像 3.3 快速生成假图像3.4 生成对抗网络(Generative Adversarial Net, GAN) 的架构3.5 使用G(z)生成伪图像 4 在Tensorflow上构建DCGANs最后 0 前言 &#…...

flutter升级+生成drift文件
1. flutter升级 可以安装fvm进行flutter version manager FVM 安装笔记 - 掘金 (juejin.cn) 使用flutter upgrade, 但是没有效果, 可能需要到我的电脑中,更改高级系统设置;改变/增加环境变量;用来加上flutter官网获取信息的内…...

[AUTOSAR][诊断管理][ECU][$34] 下载请求
文章目录 一、简介二、服务请求报文定义肯定响应支持的NRC三、示例代码34_req_dowload.c一、简介 RequestDownload(0x34)—— 下载请求 这个服务主要是用来给ECU下载数据的,最常见的应用就是在bootloader中,程序下载工具会发起下载请求,以完成ECU程序的升级。 二、服务…...

C 标准库 - <errno.h>和<float.h>详解
目录 简介 常见库宏 简介 常见库宏 <errno.h> 简介 <errno.h>头文件定义了一个名为errno的全局变量,用于表示最近发生的错误代码。errno是一个整数变量,它的值通常是一个非零的错误代码,用于指示发生了什么类型的错误。也可以…...

对于如何学习的一点思考
目录 1、学习遇到的问题 2、问题分析 3、解决思路 1、学习遇到的问题 我们经常在学习一个知识时,经常会遇到知识点凌乱、读书效率低、缺乏长期记忆等问题,主要体现在: 知识点凌乱:花时间学习了很多技术点,但是由于…...

Ensemble Methods集成学习大比拼:性能、应用场景和可视化对比总结
集成学习(Ensemble Learning)是一种机器学习范式,其中多个模型(通常称为“弱学习器”)被训练以解决相同的问题,并且通过某种方式结合它们的预测以提高整体性能。这种方法的核心思想是,多个模型比单一模型更能准确地预测未知数据。在本文中,我们将探讨多种集成学习算法,…...

【2024秋招】2023-9-16 贝壳后端开发二面
1 自我介绍 2 秒杀系统 2.1 超卖怎么解决 3 redis 3.1 过期策略 3.2 过期算法 4 kafka 4.1 说一说你对kafka的了解 4.2 如何保证事务性消息 4.3 如何保证消息不丢失 4.4 消息队列的两种通信方式 点对点模式 如上图所示,点对点模式通常是基于拉取或者轮询…...

SpringCloud 微服务全栈体系(七)
第九章 Docker 一、什么是 Docker 微服务虽然具备各种各样的优势,但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中,依赖的组件非常多,不同组件之间部署时往往会产生一些冲突。在数百上千台服务中重复部署,环境不一定一致…...

SAP ABAP 报表输出成 excel 统计图形 (RFC : GFW_PRES_SHOW_MULT)
SAP 预设了一个类型组 GFW ,做简单的excel图形输出 话不多说,直接上代码: *&---------------------------------------------------------------------* *& Report ZCYCLE057 *&----------------------------------------------…...

微信小程序如何获取地理位置
在微信小程序中,可以通过以下步骤获取用户的地理位置: 在小程序的app.json文件中配置权限: json "permission": {"scope.userLocation": {"desc": "你的位置信息将用于获取附近的服务"} }这样配置后…...

计算机网络相关硬件介绍
计算机相关硬件 计算机由运算器、控制器、存储器、输入设备和输出设备等五个逻辑计算机硬件部件组成。 一、中央处理器(CPU)(运算器、控制器) (1)运算器 运算器是对数据进行加工处理的部件ÿ…...

Megatron-LM GPT 源码分析(三) Pipeline Parallel分析
引言 本文接着上一篇【Megatron-LM GPT 源码分析(二) Sequence Parallel分析】,基于开源代码 GitHub - NVIDIA/Megatron-LM: Ongoing research training transformer models at scale ,通过GPT的模型运行示例,从三个维…...

Python---使用turtle模块+for循环绘制五角星---利用turtle(海龟)模块
首先了解涉及的新词汇,编程外国人发明的,所以大部分是和他们语言相关,了解对应意思,可以更好理解掌握。 import 英 /ˈɪmpɔːt/ n. 进口,进口商品;输入,引进;重要性;…...

Python的比较运算符查询表
据个人的编程开发经验,Python的比较运算符最常于条件判断,而条件判断是python编程中最常用的语法之一,与for或while的循环一样,功能十分强大! 在机器学习当中,或深度学习当中,在运用算法对统计…...

C/C++面试常见问题——const关键字的作用和用法
首先我们需要一下const关键字的定义,const名叫常量限定符,当const修饰变量时,就是在告诉编译器该变量只可访问不可修改,而编译器对于被const修饰的变量有一个优化,编译器不会专门为其开辟空间,而是将变量名…...

Vue3.3指北(四)
Vue3.3指北 1、WebPack - VueCLI1.1、WebPack安装VueCli1.2、vue create 创建项目1.3、项目目录结构介绍 2、ViteVue32.1、认识create-vue2.2、使用create-vue创建项目2.3、项目目录剖析2.4、ESlint代码规范及手动修复2.5、通过eslint插件来实现自动修正 3、VueRouter43.1、单页…...

vue如何使用路由拦截器
在 Vue 中使用路由拦截器需要使用 Vue Router 提供的 beforeEach 方法。beforeEach 方法会在每个路由切换前,对路由进行拦截处理。可以在这个方法中进行一些验证或者权限认证,如果满足条件则继续跳转,否则取消跳转并进行相应处理。 下面是一…...