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

【C++】stack、queue和priority_queue的模拟实现

文章目录

  • 前言
  • 一. stack
    • 1.1 stack的介绍
    • 1.2 stack的使用
    • 1.3 stack的模拟实现
  • 二. queue
    • 2.1 queue的介绍
    • 2.2 queue的使用
    • 2.3 queue的模拟实现
  • 三. deque
    • 3.1 deque的原理介绍
    • 3.2 deque的缺陷
    • 3.3 为什么选择deque作为stack和queue的底层默认容器
  • 四. priority_queue(优先队列)
    • 4.1 priority_queue的介绍
    • 4.2 priority_queue的使用
    • 4.3 priority_queue的模拟实现
      • 4.3.1 向上调整算法
      • 4.3.2 向下调整算法
      • 4.3.3 整体代码
  • 五. 仿函数
  • 最后


前言

之前已经模拟实现了vector和list,在这篇博文中,我们要对stack和queue进行模拟实现。在开始之前,先讲一个东西:容器适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口
在这里插入图片描述

在 C++ 标准库中,容器适配器(Container Adaptors)是一种特殊的容器,它们并非独立的容器类型,而是对现有容器类型进行了封装和适配,以提供特定的接口和行为。容器适配器主要有三种:stack(栈)、queue(队列)和priority_queue(优先队列)。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
其中,stack,queue,priority_queue就是通过封装容器deque(双端队列)和vector(动态数组)适配成特定的容器:容器适配器。

这里的容器适配器是设计模式的一种:适配器模式,在此之前,我们学过另外一种设计模式:迭代器模式

迭代器模式通过封装底层实现细节,并且提供统一的访问方式来访问容器
适配器模式通过封装已有的东西,再提供特定的接口来转换出想要的东西

一. stack

1.1 stack的介绍

stack的文档介绍

  1. 栈是一种容器适配器,其特点是先进后出,只能从容器的一端进行插入和提取元素。
  2. 栈是作为容器适配器被实现的,容器适配器是使用特定容器类的封装对象作为其基础容器的类,提供一组特定的成员函数来访问其元素。元素从特定容器的尾部(栈顶)被压入和弹出。
  3. 底层容器可以是任何标准容器类模板或其他专门设计的容器类。这些容器类应支持以下操作:

empty:判断容器是否为空
size:获取容器的元素个数
back:获取容器的尾部元素
push_back:在容器尾部插入一个元素
pop_back:删除容器尾部元素

  1. 标准容器vector、list、deque均符合以上要求。如果没有为stack指定一个底层容器类,则默认情况下使用deque

1.2 stack的使用

函数说明接口说明
stack()构造空的栈
empty()检测stack是否为空
size()返回stack中元素的个数
top()返回栈顶元素的引用
push()将元素val压入stack中
pop()将stack中尾部元素弹出

在这里插入图片描述

1.3 stack的模拟实现

因为stack是对容器的封装,所以默认构造函数、析构函数、赋值运算符重载函数等都不需要自己手动去实现,编译器自动生成的会调用底层容器(如vector)的默认成员函数

//防止与std库里的stack冲突
namespace MyStack {//底层容器可以是vector,list,deque,deque兼容了vector和list所有的接口//因为只学习了vector和list,就以vector作为底层容器,即为顺序栈//如果以list作为底层容器,即为链栈//template<class T, class Container = list<T>>template<class T, class Container = vector<T>>class stack{public:stack(){}void push(const T& val){_con.push_back(val);}void pop(){assert(!empty());_con.pop_back();}const T& top() const{return _con.back();}bool empty() const{return _con.empty();}size_t size() const{return _con.size();}void swap(stack& st){_con.swap(st._con);}private:Container _con;};
}

测试:

void Test()
{MyStack::stack<int> st;st.push(1);st.push(2);st.push(3);st.push(4);MyStack::stack<int> st1(st);st1.push(5);st1.swap(st);while (!st.empty()){cout << st.top() << " ";st.pop();}cout << endl;while (!st1.empty()){cout << st1.top() << " ";st1.pop();}cout << endl;
}

在这里插入图片描述

二. queue

2.1 queue的介绍

queue的文档介绍

总结:

  1. 队列是一种容器适配器,其特点为先进先出其中从容器一端插入元素,另一端提取元素
  2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列
  3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:

empty:检测队列是否为空
size:返回队列中有效元素的个数
front:返回队头元素的引用
back:返回队尾元素的引用
push_back:在队列尾部入队列
pop_front:在队列头部出队列

  1. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

在这里插入图片描述

2.2 queue的使用

函数声明接口说明
queue()构造空的队列
empty()检测队列是否为空,是就返回true,否则返回false
size()返回队列中有效元素的个数
front()返回队头元素的引用
back()返回队尾元素的引用
push()在队尾将元素val入队列
pop()将队头元素出队列

在这里插入图片描述

2.3 queue的模拟实现

与stack一样,我们不需要手动去实现默认成员函数,编译器自动生成的就满足需求了。

//防止与std库里的queue冲突
namespace MyQueue {//底层容器可以是list和deque,这里使用较为熟悉的listtemplate<class T, class Container = list<T>>class queue{public:void push(const T& val){_con.push_back(val);}void pop(){assert(!empty());_con.pop_front();}const T& front() const{assert(!empty());return _con.front();}const T& back() const{assert(!empty());return _con.back();}bool empty() const{return _con.empty();}size_t size() const{return _con.size();}void swap(queue& q){_con.swap(q._con);}private:Container _con;};
}

注意不能使用vector作为底层容器,因为vector不支持高效的头部删除操作

测试:

void Test()
{MyQueue::queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);MyQueue::queue<int> q1(q);q1.push(5);q1.push(6);q.swap(q1);while (!q.empty()){cout << q.front() << " ";q.pop();}cout << endl;while (!q1.empty()){cout << q1.front() << " ";q1.pop();}cout << endl;
}

在这里插入图片描述

三. deque

vector和list各有缺点:

vector:1.头部中部插入删除效率低;2.要扩容
list:1.不支持随机访问;2.cpu高速缓存命中率低

那有没有一种完美的容器,可以将两者的优点结合,缺点抹除呢?

答案是有的,这个容器就是deque。下面来了解一下deque。

3.1 deque的原理介绍

deque(双端队列):是一种双开口的“连续”空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高,且支持随机访问。

在这里插入图片描述
deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:

map数组存储所有的缓冲区,当缓冲区不够用了,就创建新的map数组,将旧的map数组存储的缓冲区地址拷贝给新的map数组,最后将旧的map数组释放掉即可

双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:

在这里插入图片描述
那deque是如何借助其迭代器维护其假想连续的结构呢?
在这里插入图片描述
迭代器存储四个成员:first(指向当前缓冲区的头部),last(指向当前缓冲区的尾部),cur(指向当前元素的指针),node(指向当前缓冲区地址在中控数组存储的位置)。

deque的随机下标访问
分为两种情况:

  1. 访问的元素在当前缓冲区

直接移动cur指针到指定位置即可。

  1. 访问的元素不在当前缓冲区。

因为buffer数组的大小是固定的,所以我们可以先用下标/buffer数组的大小,找到要访问的元素在第几个buffer数组里;再根据下标%buffer数组的大小,得到要访问的元素在buffer数组的第几个位置。

deque的随机下标访问还是挺麻烦的,也没有vector快,虽然兼容了vector和list,但是它的优点也不突出。

3.2 deque的缺陷

与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的

与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

但是,deque有一个致命缺陷不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构

deque的使用场景:

1、中部插入删除操作少,头尾插入删除操作多
2、偶尔进行随机下标访问

3.3 为什么选择deque作为stack和queue的底层默认容器

stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;queue是先进先出的特殊线性数据结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

  1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作
  2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,queue不仅效率高,而且内存使用率高

结合了deque的优点,而完美的避开了其缺陷。

感兴趣的可以看一下deque的模拟实现:
c++编程(17)——deque的模拟实现(1)迭代器篇
c++编程(18)——deque的模拟实现(2)容器篇
deque的模拟实现源代码

四. priority_queue(优先队列)

4.1 priority_queue的介绍

priority_queue的文档介绍

在这里插入图片描述

总结:

  1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的
  2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。
  3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从特定容器的"尾部"弹出,其称为优先队列的顶部。
  4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:

empty():检测容器是否为空
size():返回容器中有效元素个数
front():返回容器中第一个元素的引用
push_back():在容器尾部插入元素
pop_back():删除容器尾部元素

  1. 标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector
  2. 需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数make_heap、push_heap和pop_heap来自动完成此操作。

4.2 priority_queue的使用

优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆

函数声明接口说明
priority_queue()/priority_queue(first,last)构造一个空的优先级队列
empty()检测优先级队列是否为空,是返回true,否则返回false
top()返回优先级队列中最大(最小元素),即堆顶元素
push(x)在优先级队列中插入元素x
pop()删除优先级队列中最大(最小)元素,即堆顶元素
  1. 存储的是内置类型
void Test()
{//默认情况下,创建的是大堆vector<int> v{ 3,2,7,6,0,4,1,9,8,5 };priority_queue<int> q1;for (auto& e : v){q1.push(e);}cout << q1.top() << endl;//如果要创建小堆,将第三个模板参数换成greater比较方式priority_queue<int, vector<int>, greater<int>> q2(v.begin(), v.end());cout << q2.top() << endl;
}
  1. 如果在priority_queue中放自定义类型的数据,用户需要在自定义类型中提供 > 或者 < 的重载
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}friend ostream& operator<<(ostream& _cout, const Date& d);
private:int _year;int _month;int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}
void Test()
{// 大堆,需要用户在自定义类型中提供<的重载priority_queue<Date> q1;q1.push(Date(2018, 10, 29));q1.push(Date(2018, 10, 28));q1.push(Date(2018, 10, 30));cout << q1.top() << endl;// 如果要创建小堆,需要用户提供>的重载priority_queue<Date, vector<Date>, greater<Date>> q2;q2.push(Date(2018, 10, 29));q2.push(Date(2018, 10, 28));q2.push(Date(2018, 10, 30));cout << q2.top() << endl;
}

在这里插入图片描述

4.3 priority_queue的模拟实现

因为priority_queue的底层结构就是堆,因此我们只需对其进行封装即可。

如果对堆不熟悉的可以看这篇博客:数据结构:二叉树(堆)的顺序存储

4.3.1 向上调整算法

作用:向上调整当前结点,使其满足堆结构。
主要应用:插入一个结点时(在堆尾),最后一个结点向上调整满足堆结构。

在这里插入图片描述

void AdJustUp(int child)
{int parent = (child - 1) / 2;if (parent >= 0 && _con[parent]<_con[child]) {std::swap(_con[parent], _con[child]);AdJustUp(parent);}
}

4.3.2 向下调整算法

作用:向下调整当前结点,使其满足堆结构。
主要应用:1. 向下调整算法建堆;2.删除堆顶结点时,第一个结点(堆顶)与最后一个结点(堆底)交换,将最后一个结点删除后,让第一个结点(堆顶)向下调整满足堆结构。

在这里插入图片描述
在这里插入图片描述

void AdjustDown(int parent)
{int child = 2 * parent + 1;if (child + 1 < _con.size() && _con[child]<_con[child + 1]) {child++;}if (child < _con.size() && _con[parent]<_con[child]) {std::swap(_con[child], _con[parent]);AdjustDown(child);}
}

4.3.3 整体代码

namespace Mypriority_queue {template<class T, class Container = vector<T>>class priority_queue{public://强制生成默认构造priority_queue() = default;template<class InputIterator>priority_queue(InputIterator first, InputIterator last):_con(first, last){//使用向下调整算法建堆for (int i = (_con.size() - 2) / 2; i >= 0; i--){AdjustDown(i);}}void AdJustUp(int child){int parent = (child - 1) / 2;if (parent >= 0 && _con[parent]<_con[child]) {std::swap(_con[parent], _con[child]);AdJustUp(parent);}}void push(const T& val){_con.push_back(val);AdJustUp(_con.size() - 1);}void AdjustDown(int parent){int child = 2 * parent + 1;if (child + 1 < _con.size() && _con[child]<_con[child + 1]) {child++;}if (child < _con.size() && _con[parent]<_con[child]) {std::swap(_con[child], _con[parent]);AdjustDown(child);}}void pop(){assert(!empty());std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}const T& top() const{assert(!empty());return _con[0];}bool empty() const{return _con.empty();}bool size() const{return _con.size();}void swap(priority_queue& q){_con.swap(q._con);}private:Container _con;};
}

为什么使用向下调整算法建堆?

因为向下调整算法建堆的时间复杂度为O(N)向上调整算法建堆的时间复杂度为O(NlogN),优先用时间复杂度低的。

注意向下调整算法建堆要从最后一个结点的父节点开始,依次到根节点后结束

整体已经实现的差不多了,还有最后一个:仿函数,接下来我们来看一下仿函数是如何实现大小堆的。

五. 仿函数

仿函数实际上就是一个类,通过重载operator(),可以让我们像使用函数一样去使用这个类。

namespace GL
{template<class T>struct less {bool operator()(const T& left, const T& right) const{return left < right;}};template<class T>struct greater {bool operator()(const T& left, const T& right) const{return left > right;}};
}
void Test()
{GL::greater<int> g;cout << g(2, 3) << endl;GL::less<int> l;cout << l(2, 3) << endl;
}

在这里插入图片描述
less是判断第一个参数是否小于第二个参数,greater是判断第一个参数是否大于第二个参数。

通过对仿函数的了解,我们知道了priority_queue的第三个模板参数就是用来控制大小堆的(默认为less,就是大堆,如果传的是greater,就是小堆)。

namespace Mypriority_queue {template<class T>struct less {bool operator()(const T& left, const T& right) const{return left < right;}};template<class T>struct greater {bool operator()(const T& left, const T& right) const{return left > right;}};template<class T, class Container = vector<T>,class Compare = less<T>>class priority_queue{public://强制生成默认构造priority_queue() = default;template<class InputIterator>priority_queue(InputIterator first, InputIterator last):_con(first, last){//使用向下调整算法建堆for (int i = (_con.size() - 2) / 2; i >= 0; i--){AdjustDown(i);}}void AdJustUp(int child){int parent = (child - 1) / 2;if (parent >= 0 && Compare()(_con[parent],_con[child])) {std::swap(_con[parent], _con[child]);AdJustUp(parent);}}void push(const T& val){_con.push_back(val);AdJustUp(_con.size() - 1);}void AdjustDown(int parent){int child = 2 * parent + 1;if (child + 1 < _con.size() && Compare()(_con[child],_con[child + 1])) {child++;}if (child < _con.size() && Compare()(_con[parent],_con[child])) {std::swap(_con[child], _con[parent]);AdjustDown(child);}}void pop(){assert(!empty());std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}const T& top() const{assert(!empty());return _con[0];}bool empty() const{return _con.empty();}bool size() const{return _con.size();}void swap(priority_queue& q){_con.swap(q._con);}private:Container _con;};
}

测试:

void Test()
{vector<int> v = { 2,3,1,4,7,6,5 };Mypriority_queue::priority_queue<int> q1(v.begin(), v.end());while (!q1.empty()){cout << q1.top() << " ";q1.pop();}cout << endl;Mypriority_queue::priority_queue<int, vector<int>, Mypriority_queue::greater<int>> q2(v.begin(), v.end());while (!q2.empty()){cout << q2.top() << " ";q2.pop();}cout << endl;
}

在这里插入图片描述

再来看一下以下这段代码:

void Test()
{Mypriority_queue::priority_queue<Date*> q;q.push(new Date(2025, 1, 1));q.push(new Date(2025, 2, 1));q.push(new Date(2025, 3, 1));while (!q.empty()){cout << *q.top() << " ";q.pop();}cout << endl;
}

在这里插入图片描述
在这里插入图片描述

为什么两次运行的结果是不一样的,还是错误的呢?

因为存储的类型为指针类型Date*,而仿函数默认比较的就是Date*,因为地址是随机性的,而堆顶是地址值最大的Date对象,所以每次运行的结果都不一样。

解决办法就是自己再写一个专门用于比较Date*的仿函数:

struct Less
{bool operator()(const Date* d1, const Date* d2){return *d1 < *d2;}
};
struct Greater
{bool operator()(const Date* d1, const Date* d2){return *d1 > *d2;}
};
void Test()
{Mypriority_queue::priority_queue<Date*, vector<Date*>, Less> q;q.push(new Date(2025, 1, 1));q.push(new Date(2025, 2, 1));q.push(new Date(2025, 3, 1));while (!q.empty()){cout << *q.top() << " ";q.pop();}cout << endl;Mypriority_queue::priority_queue<Date*, vector<Date*>, Greater> q1;q1.push(new Date(2025, 1, 1));q1.push(new Date(2025, 2, 1));q1.push(new Date(2025, 3, 1));while (!q1.empty()){cout << *q1.top() << " ";q1.pop();}cout << endl;
}

在这里插入图片描述

最后

stack、queue、priority_queue的模拟实现到这里就结束了,对以上内容有异议或者需要补充的,欢迎大家来讨论!

本文整体代码:stack,queue,priority_queue的模拟实现

相关文章:

【C++】stack、queue和priority_queue的模拟实现

文章目录 前言一. stack1.1 stack的介绍1.2 stack的使用1.3 stack的模拟实现 二. queue2.1 queue的介绍2.2 queue的使用2.3 queue的模拟实现 三. deque3.1 deque的原理介绍3.2 deque的缺陷3.3 为什么选择deque作为stack和queue的底层默认容器 四. priority_queue&#xff08;优…...

Jmeter数据库url开关设置+常用Beanshell

1、数据库url开关设置 &#xff08;79 90&#xff09; jdbc:mysql://test.lemonban.com:3306/future?allowMultiQueries-true&characterEncodingUTF-8 多条查询开关&#xff1a;allowMultiQueriestrue 字符集配置:characterEncodingUTF-8 2、用BeanShell提取Map中的方…...

NtripShare 2025第一季度主要技术进展

GNSS方面 1、开源GNSS接收机配置软件基础版本。 2、商业版本GNSS接收机配置软件&#xff0c;增加PPP、文件保存、前端解算&#xff08;静态、RTK-Static&#xff09;&#xff0c;前端坐标转换。 3、GNSS接收机配置软件全面适配米尔T133i硬件方案。 视觉检测方面 1、做出第…...

Linux系统编程之内存映射

概述 内存映射是操作系统提供的一种机制&#xff0c;使得文件或设备的内容可以直接映射到进程的虚拟地址空间中。这意味着&#xff0c;我们可以像访问数组一样读写文件内容&#xff0c;而不需要显式地调用I/O函数进行数据传输。内存映射适用于多种应用场景&#xff0c;包括但不…...

一文详解Adobe Photoshop 2025安装教程

Adobe Photoshop下载安装和使用教程 Adobe Photoshop&#xff0c;简称“PS”&#xff0c;是由Adobe Systems开发和发行的图像处理软件。Photoshop主要处理以像素所构成的数字图像。使用其众多的编修与绘图工具&#xff0c;可以有效地进行图片编辑和创造工作&#xff0c…...

ShenNiusModularity项目源码学习(23:ShenNius.Admin.Mvc项目分析-8)

用户列表页面用于检索、新建、编辑、删除系统用户&#xff0c;同时设置用户角色。该页面对应的文件Index.cshtml位于ShenNius.Admin.Mvc项目的Areas\Sys\Views\User内&#xff0c;同目录下还有Modify.cshtml&#xff08;新建、编辑用户&#xff09;、SetRole.cshtml&#xff08…...

vue中 vue.config.js反向代理

新建一个node 服务 1 npm init -y //创建一个package.json 2.npm i express 3. 新建一个app.js 4.键入代码 const express require("express") const app express()app.get("/user",(req,res)>{res.send({"name":"good"…...

AIGC赋能智慧医疗:从影像诊断到个性化治疗的革命性突破

一、医疗AIGC技术架构 1.1 医疗场景技术挑战 医疗环节 行业痛点 AIGC解决方案 影像诊断 人工阅片效率低 多模态病灶分割与分级系统 病历管理 结构化程度低 语音转文本智能编码 药物研发 周期长成本高 分子生成与虚拟筛选 个性化治疗 方案标准化不足 基因组学临床数据融合模型 1…...

Yarn 安装与使用教程

Yarn 安装与使用教程 Yarn 是一个由 Facebook 开发的 JavaScript 包管理工具&#xff0c;它比传统的 npm 更加高效、可靠&#xff0c;并且在性能上有所提升。Yarn 主要解决了 npm 安装速度慢、并发性差、缓存机制不完善等问题&#xff0c;它提供了更快的安装速度、更稳定的依赖…...

机器学习之二:指导式学习

正如人们有各种各样的学习方法一样&#xff0c;机器学习也有多种学习方法。若按学习时所用的方法进行分类&#xff0c;则机器学习可分为机械式学习、指导式学习、示例学习、类比学习、解释学习等。这是温斯顿在1977年提出的一种分类方法。 有关机器学习的基本概念&#xff0c;…...

【学习笔记】检索增强生成(RAG)技术

检索增强生成&#xff08;RAG&#xff09;技术&#xff1a;原理、实现与发展趋势 1. RAG技术概述 检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;RAG&#xff09;是一种将信息检索与生成模型相结合的技术&#xff0c;旨在增强大型语言模型的知识能力和…...

计算机视觉——对比YOLOv12、YOLOv11、和基于Darknet的YOLOv7的微调对比

概述 目标检测领域取得了巨大进步&#xff0c;其中 YOLOv12、YOLOv11 和基于 Darknet 的 YOLOv7 在实时检测方面表现出色。尽管这些模型在通用目标检测数据集上表现卓越&#xff0c;但在 HRSC2016-MS&#xff08;高分辨率舰船数据集&#xff09; 上对 YOLOv12 进行微调时&…...

Pygame跨平台打包:将游戏发布到Windows、Mac和Linux

Pygame跨平台打包:将游戏发布到Windows、Mac和Linux 引言 在游戏开发的世界中,Pygame 是一个非常受欢迎的库,它使得使用 Python 编写 2D 游戏变得简单而有趣。然而,当你完成了一个游戏并希望将其发布给更多的玩家时,如何将你的游戏打包成可以在不同操作系统上运行的可执…...

关于图论的知识

如果一个无向图有 $n\times (n-1)\div 2$ 条边&#xff0c;称为**完全图** 如果一个完全图任意两个点都可以互相到达&#xff0c;称为**连通图** 一个包含 $dfs$ 与 $bfs$ 的图的遍历程序 程序可做到的&#xff1a; 1、每一行输出一个 **搜索树** 2、$dfs$ 与 $bfs$ 并存 c…...

365打卡第R3周: RNN-心脏病预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 &#x1f3e1; 我的环境&#xff1a; 语言环境&#xff1a;Python3.10 编译器&#xff1a;Jupyter Lab 深度学习环境&#xff1a;torch2.5.1 torchvision0…...

如何解决IDE项目启动报错 error:0308010C:digital envelope routines::unsupported 问题

如何解决IDE项目启动报错 error:0308010C:digital envelope routines::unsupported 问题 在现代软件开发过程中&#xff0c;开发人员通常使用集成开发环境&#xff08;IDE&#xff09;如IntelliJ IDEA、Visual Studio Code&#xff08;VSCode&#xff09;等进行Node.js项目开发…...

嵌入式学习笔记 - HAL_xxx_MspInit(xxx);函数

使用cubeMX生成的HAL库函数中&#xff0c;所有外设的初始化函数HAL_xxx_Init(&xxxHandle)中都存在有此调用函数&#xff0c;此调用函数其实是对各外设模块比如UART&#xff0c;I2C等的底层硬件初始化&#xff0c;包括UART时钟&#xff0c;以及UART用到的GPIO的工作模式以及…...

Dify框架面试内容整理-Dify框架

什么是Dify框架? Dify框架是一个开源的AI应用开发平台,专注于帮助开发者和非技术人员快速构建、部署和管理基于大语言模型(如GPT系列、国产开源模型)的应用。 Dify框架的特点:...

计算机网络的五层结构(物理层、数据链路层、网络层、传输层、应用层)到底是什么?

文章目录 五层结构1. 物理层&#xff08;Physical Layer&#xff09;2. 数据链路层&#xff08;Data Link Layer&#xff09;3. 网络层&#xff08;Network Layer&#xff09;4. 传输层&#xff08;Transport Layer&#xff09;5. 应用层&#xff08;Application Layer&#xf…...

【计算机视觉】CV实战项目 -深度解析PaddleSegSharp:基于PaddleSeg的.NET图像分割解决方案

深度解析PaddleSegSharp&#xff1a;基于PaddleSeg的.NET图像分割解决方案 技术背景与项目概述核心功能与特点实战部署指南环境要求硬件要求软件依赖 项目结构快速开始1. 获取项目2. 准备模型文件3. 运行示例 高级使用技巧模型切换背景替换性能优化 常见问题与解决方案技术原理…...

面试新收获-大模型学习

大模型原理 Transformer 架构与自注意力机制 Transformer 是当前大多数大模型采用的核心架构&#xff0c;由编码器-解码器组成&#xff0c;摒弃了传统 RNN 的顺序处理方式。Transformer 中关键在于多头自注意力机制&#xff08;Multi-Head Self-Attention&#xff09;&#xf…...

《Keras 3部署全攻略:从新手到实战高手》

《Keras 3部署全攻略:从新手到实战高手》 一、引言:开启 Keras 3 部署之旅 在深度学习的广阔领域中,Keras 一直以其简洁易用、高度模块化的特性,深受开发者的喜爱,被誉为深度学习的 “福音”。而如今,Keras 3 的强势登场,更是为这个领域注入了全新的活力。它像是一位集…...

如何修改npm的全局安装路径?

修改 npm 的全局安装路径可以通过以下步骤完成&#xff0c;确保全局包&#xff08;使用 -g 安装的模块&#xff09;和缓存文件存储到自定义路径。以下是详细步骤&#xff1a; 1. 创建自定义路径的目录 在目标路径下创建两个文件夹&#xff0c;分别用于存储全局模块和缓存文件…...

计算机网络 | Chapter1 计算机网络和因特网

&#x1f493;个人主页&#xff1a;mooridy-CSDN博客 &#x1f493;文章专栏&#xff1a;《计算机网络&#xff1a;自定向下方法》 大纲式阅读笔记_mooridy的博客-CSDN博客 &#x1f339;关注我&#xff0c;和我一起学习更多计算机网络的知识 &#x1f51d;&#x1f51d; 目录 …...

前端面试 HTML篇

src和href的区别 src和href都是用来加载外部资源&#xff0c;区别如下 src&#xff1a;当浏览器解析到该元素时&#xff0c;会暂停其他资源的加载和处理&#xff0c;直到该资源加载完成。 它会将资源内容嵌入到当前标签所在的位置&#xff0c;将其指向的资源下载应用到文档内…...

Prometheus、Zabbix 和 Nagios 这三个工具的对100个节点的部署设计的信息流

Prometheus 1. 基本组件及角色 Prometheus主要由Prometheus Server、Exporter、Alertmanager和Grafana(可选)等组件构成。 Prometheus Server:负责数据的收集、存储和查询,以及规则的评估。Exporter:部署在被监控节点上,负责收集节点的各种指标数据。Alertmanager:负责…...

Tableau 基础表制作

目录 1.数据连接 2. 数据可视化 3. 基础表制作 3.1 对比分析&#xff1a;比大小 1. 柱状图 2. 条形图 3. 热力图 4. 气泡图 5. 词云 3.2 变化分析&#xff1a;看趋势 1. 折线图 2. 面积图 3.3 构成分析&#xff1a;看占比 1. 饼图 2. 树地图 3. 堆积图 3.4 关…...

openAICEO山姆奥特曼未来预测雄文之三个观察

《三个观察》 山姆奥特曼 这篇文章主要讲的是关于AGI&#xff08;人工通用智能&#xff09;的未来发展及其对社会的影响&#xff0c;用大白话总结如下&#xff1a; 核心观点&#xff1a; AGI是什么&#xff1f; AGI是一种能像人类一样解决各种复杂问题的智能系统&#xff0c;比…...

springboot入门-service层构造器注入原理

在 Spring Boot 中&#xff0c;通过构造器注入的方式将 Repository&#xff08;JPA&#xff09;或 Mapper&#xff08;MyBatis&#xff09;注入到 Service 层的原理及示例如下&#xff1a; 1. 构造器注入的原理 依赖注入&#xff08;DI&#xff09;机制&#xff1a; Spring 容…...

JavaScript 笔记 --- part6 --- JS进阶 (part1)

JS 进阶(part1) 作用域 局部作用域 定义: 局部作用域指的是在函数内部定义的变量&#xff0c;只能在函数内部访问&#xff0c;外部不能访问。 特点: 局部作用域变量只能在函数内部或代码块中访问&#xff0c;外部不能访问。 分类: 函数作用域: 指的是在函数内部定义的变量&…...

使用matplotlib绘制Raincloud图/云雨图/柱状图/小提琴图

需求&#xff1a; 使用Python的matplotlib绘制数据分布、数据箱型图、数据散点图 参考&#xff1a; https://blog.csdn.net/weixin_39559994/article/details/128197965?fromshareblogdetail&sharetypeblogdetail&sharerId128197965&sharereferPC&sharesource…...

BT152-ASEMI机器人率器件专用BT152

编辑&#xff1a;LL BT152-ASEMI机器人率器件专用BT152 型号&#xff1a;BT152 品牌&#xff1a;ASEMI 封装&#xff1a;TO-220F 批号&#xff1a;最新 引脚数量&#xff1a;3 封装尺寸&#xff1a;如图 特性&#xff1a;单向可控硅 工作结温&#xff1a;-40℃~150℃ …...

【Redis——通用命令】

文章目录 Redis为什么快&#xff1f;生产环境的概念Redis中最核心的两个命令get&#xff1a;通过key拿valueset&#xff1a;将key和value存入数据库 其他通用命令keysexist判定key是否存在delexpire&#xff1a;为指定的key设置一个过期时间TTL&#xff08;Time To Live&#x…...

qt之开发大恒usb3.0相机一

1.在大恒相机给的sample里没有看见qt开发的demo. 第一步先运行c sdk中中的demo&#xff0c;看了下代码&#xff0c;大恒使用的UI框架是MFC.然后 vs2022编译。运行结果 第一步&#xff0c;先用qt进行坐下页面布局&#xff0c;如下图&#xff08;保存图片的地方做了些更改&#…...

系列位置效应——AI与思维模型【80】

一、定义 系列位置效应思维模型是指在一系列事物或信息的呈现过程中&#xff0c;人们对于处于系列开头和结尾部分的项目的记忆效果优于中间部分项目的现象。具体而言&#xff0c;开头部分的记忆优势被称为首因效应&#xff0c;结尾部分的记忆优势被称为近因效应。这种效应反映…...

解决conda虚拟环境安装包却依旧安装到base环境下

最近跑项目装包装到几度崩溃&#xff0c;包一直没有安装到正确位置&#xff0c;为此写下这篇文章记录一下&#xff0c;也希望能帮到有需要的人。&#xff08;此文章开发环境为anaconda和window&#xff09; 方法一 先conda deactivate,看到&#xff08;base&#xff09;消失…...

设计看似完美却测不过? Intra-Pair Skew 是「讯号完整性(Signal Integrity)」里最隐形的杀手

各位不知道有没有遇过&#xff0c;一对很长的差分走线&#xff0c;看起来很正常&#xff0c;但是测试结果偶尔会fail偶尔会pass&#xff0c;不像是软件问题&#xff0c;也不像是制程问题。 看了一下Layout&#xff0c;发现阻抗匹配控制的非常好&#xff0c;TDR测试也显示阻抗好…...

使用MyBatis注解方式的完整示例,涵盖CRUD、动态SQL、分页、事务管理等场景,并附详细注释和对比表格

以下是使用MyBatis注解方式的完整示例&#xff0c;涵盖CRUD、动态SQL、分页、事务管理等场景&#xff0c;并附详细注释和对比表格&#xff1a; 项目结构 mybatis-annotation-demo/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com.example/…...

【头脑风暴】加权平均

一些加权平均而不是算术平均的思路&#xff0c;启发来源&#xff1a;ACLS,WACLS。 简单平均假设所有样本的误差和噪声特性相同&#xff0c;但在实际电路中&#xff0c;不同阶段、不同时间点的样本价值&#xff08;对最终精度的贡献&#xff09;是不同的。​​加权平均的核心思想…...

DAM-3B,英伟达推出的多模态大语言模型

DAM-3B是什么 DAM-3B&#xff08;Describe Anything 3B&#xff09;是英伟达推出的一款多模态大语言模型&#xff0c;专门用于为图像和视频中的特定区域生成详细描述。用户可以通过点、边界框、涂鸦或掩码等方式来标识目标区域&#xff0c;从而得到精准且符合上下文的文本描述…...

2025年暨南大学 ACM校赛分析与题解

文章目录 C.最长公共前缀D.排列H.回文串 法不定法&#xff0c;在于因时因势AC不了就是还得加练&#xff01; C.最长公共前缀 字典树模版题目&#xff0c;不了解字典树的同学&#xff0c;可以看我的另一篇博客 算法 之 字典树 class Node: # 和模版题目相似&#xff0c;但是多…...

图像处理——边缘检测

1 概述 边缘检测是图像处理和计算机视觉中的一项基本技术&#xff0c;用于识别图像中亮度变化剧烈的像素点&#xff0c;这些像素点通常对应于物体的边界。它通过检测图像中亮度或颜色变化显著的区域&#xff0c;提取出物体的轮廓&#xff0c;常用于计算机视觉、图像处理和模式识…...

认识哈希以及哈希表的模拟实现

文章目录 1.什么是哈希2.哈希函数2.1 除留余数法/除法散列法2.2 乘法散列法2.3 全域散列法 3.哈希冲突4.解决哈希冲突的方法4.1 开放定址法4.1.1 用除留余数法和线性探测模拟实现简单的哈希表 4.2 链地址法4.2.1 用除留余数法和链地址法模拟实现简单的哈希表 1.什么是哈希 概念…...

【Castle-X机器人】二、智能导览模块安装与调试

持续更新。。。。。。。。。。。。。。。 【Castle-X机器人】智能导览模块安装与调试 二、智能导览模块安装与调试2.1 智能导览模块安装2.2 智能导览模块调试2.2.1 红外测温传感器测试2.2.2 2D摄像头测试 二、智能导览模块安装与调试 2.1 智能导览模块安装 使用相应工具将智能…...

硬件须知的基本问题2

目录 1、典型电路 1. DC5V 转 DC3.3V 电路 2. 通信电路 2、STM32F103RCT6 最小系统如何设计搭建电路 1. 电源电路 2. 复位电路 3. 时钟电路 4. 下载电路 5. 单片机连接连接 3、请列举你所知道的二极管型号&#xff1f; 1. 整流二极管 2. 小信号二极管 3. 肖特基二极管 4. 超…...

Dify 使用 excel 或者 csv 文件创建知识库

Dify 使用 excel 或者 csv 文件创建知识库 1. 创建知识库2. 创建聊天助手3. 其他 1. 创建知识库 创建知识库&#xff0c;导入excel/csv文件&#xff0c; 文件内容&#xff0c; 单击 “预览块”&#xff0c;可以确认会生成多个键值对的块&#xff0c; 配置 Embedding 模型和检索…...

深入理解二叉树遍历:递归与栈的双重视角

二叉树的遍历前序遍历中序遍历后续遍历总结 二叉树的遍历 虽然用递归的方法遍历二叉树实现起来更简单&#xff0c;但是要想深入理解二叉树的遍历&#xff0c;我们还必须要掌握用栈遍历二叉树&#xff0c;递归其实就是利用了系统栈去遍历。特此记录一下如何用双重视角去看待二叉…...

通过gap看margin和padding在布局中的应用

在CSS布局中&#xff0c;控制元素之间的间距有多种方式&#xff1a;margin、padding&#xff0c;还有新晋的gap属性。虽然选择多了&#xff0c;但这也带来了不少头疼的问题。比如&#xff0c;你的自定义组件到底该不该加margin&#xff1f;如果加了&#xff0c;那在使用这个组件…...

图像畸变-径向切向畸变实时图像RTSP推流

实验环境 注意&#xff1a;ffmpeg进程stdin写入两张图片的时间间隔不能太长&#xff0c;否则mediamtx会出现对应的推流session超时退出。 实验效果 全部代码 my_util.py #进度条 import os import sys import time import shutil import logging import time from datetime i…...

2025最新Facefusion3.1.2使用Docker部署,保姆级教程,无需配置环境

Docker部署Facefusion 环境 windows10 Facefusion3.1.2 安装 拉取源代码 git clone https://github.com/facefusion/facefusion-docker.git 此处如果拉不下来&#xff0c;需要科学上网&#xff0c;不会的可以找我。 运行容器 将Dockerfile.cpu文件中的的From python:3.…...