【C++/STL深度剖析】stack和queue的详细概念和使用(图文详解,初学者必看!!)

目录

一、前言

二、stack 的详细解析

🔥 stack的介绍🔥

🔥 stack的构造🔥

🔥 stack的常用接口🔥

💧push

💧top 

💧pop

💧empty 

💧size 

💧swap 

三、queue 的详细解析

🔥 queue的介绍🔥

🔥 queue的构造🔥

🔥 queue的常用接口🔥 

💧push 

💧size 

💧front 

💧back 

💧pop  

💧empty  

💧swap   

四、容器适配器 

🥝 什么是适配器 ?

🍍stack 和 queue 的底层结构

🍇deque的原理介绍 

🍑deque 的底层结构

🍉deque 的优缺点 

🍈  选择 deque 的原因

六、 模拟实现 【stack】和 【queue】

🔥 stack 的模拟实现🔥  

🔥 queue 的模拟实现🔥  

七、总结 

八、共勉 


一、前言

        最近在刷 leetcode  的时候,发现 stack和queue 都还没弄明白😖,但是 STL 的强大是众所周知滴,早晚都是要解决滴,因此专门写下这篇文章,以供自己复习和各位老铁使用,快速的回忆 stack和queue 的用法,让你找回自信,不用再竞赛的时候颜面尽失。
       本次博客主要讲解
stack和queue 的常用接口,由于篇幅过长,stack和queue 的常考面试题,下一篇博客来阐述,请大家持续关注我O!!

二、stack 的详细解析

🔥 stack的介绍🔥

【stack】是一种 特殊的数据结构,也是一种 容器适配器,主要特点为:【先进后出】,主要操作有:入栈、出栈、查看栈顶元素、判断栈空等在原则上是不允许进行 中部底部 操作的,这样会破坏栈结构的完整性。

从下图,可以看到 栈【stack】是作为容器适配器被实现,容器适配器对特定类封装作为其底层容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层,元素特定容器的尾部(即栈顶)被压入和弹出。(容器适配器本文的后面会详细讲解,这里先了解一下它 和 栈 的关系)

可以看出,栈有两个模板参数

  • 参数1:T 栈中的元素类型,同时也是底层容器中的元素类型
  • 参数2:Container 实现栈时用到的底层容器,这里为缺省参数,缺省结构为 双端队列 deque

也就是说,【stack】底层容器可以是任何标准的容器类模板或者一些其特定的容器类,这些容器应该支持一下操作:

  • empty :判空操作
  • back :获取尾部元素操作
  • push_back :尾部插入元素操作
  • pop_back :尾部删除元素操作

标准容器 vector、deque、list 均符合上面的这些要求,默认情况下,如果没有为 【stack】指定特定的顶层容器,默认情况下使用 deque (这一点会在本文,后下容器适配器,详细讲解)


🔥 stack的构造🔥

它的构造方式如下:

(1)使用默认的容器适配器构造一个空栈

stack<int> s; // 默认底层容器为 deque 

(2)使用其它的容器适配器构造一个空栈

stack<int, vector<int>> sv;   // 显示实例化 底层容器为 vector
stack<int, list<int>> sl;     // 显示实例化,底层容器为 list

代码测试: 

#include <iostream>
#include <stack>
#include <vector>
#include <list>using namespace std;int main()
{stack<int> s;	//默认底层容器为 dequestack<int, vector<int>> sv;	//显示实例化底层容器为 vectorstack<char, list<char>> sl;	//显示实例化底层容器为 listcout << typeid(s).name() << endl;	//查看具体类型cout << typeid(sv).name() << endl;cout << typeid(sl).name() << endl;return 0;
}

注意: 关于参数3 allocator 是空间配置器,这里先不作讲解,后续再学习

🔥 stack的常用接口🔥

相对于前面学习的容器(vector、list、string),【stack】的接口更简单也更少,基本的使用函数如下: 

💧push

在 栈【stack】顶部插入一个新元素,位于其当前顶部元素之上。 

代码示例: 

void test_stack()
{stack<int> st;  // 构造一个栈 对象 --- 此时为空栈,底层为 dequest.push(1);st.push(2);st.push(3);     // 向 栈 中插入 元素 【1,2,3,4,5】st.push(4);st.push(5);
}

💧top 

返回栈【stack】的顶部元素 

 代码示例:

void test_stack()
{stack<int> st;  // 构造一个栈 对象 --- 此时为空栈,底层为 dequest.push(1);st.push(2);st.push(3);     // 向 栈 中插入 元素 【1,2,3,4,5】st.push(4);st.push(5);cout << st.top() << endl; // 返回栈的 顶部元素  -- 【5】
}

运行结果展示: 


💧pop

 删除 栈【stack】顶部的元素,有效的将其空间大小 -- 减少 1

 代码示例:

void test_stack()
{stack<int> st;  // 构造一个栈 对象 --- 此时为空栈,底层为 dequest.push(1);st.push(2);st.push(3);     // 向 栈 中插入 元素 【1,2,3,4,5】st.push(4);st.push(5);cout << st.top() << endl; // 返回栈的 顶部元素  -- 【5】st.pop();                 // 删除栈顶元素 -- [5]cout << st.top() << endl; // 返回栈的 顶部元素  -- 【4】
}

 运行结果展示: 


💧empty 

返回栈【stack】是否为空,即它的空间大小是否为 0

因为栈【stack】是不支持遍历的,所以这个接口可以用来实现栈的遍历 

代码示例:

void test_stack()
{stack<int> st;  // 构造一个栈 对象 --- 此时为空栈,底层为 dequest.push(1);st.push(2);st.push(3);     // 向 栈 中插入 元素 【1,2,3,4,5】st.push(4);st.push(5);while(!st.empty()){cout << st.top() << " ";st.pop();        }
}

 运行结果展示: 


💧size 

返回栈【stack】中元素个数 

 代码示例:

void test_stack()
{stack<int> st;  // 构造一个栈 对象 --- 此时为空栈,底层为 dequest.push(1);st.push(2);st.push(3);     // 向 栈 中插入 元素 【1,2,3,4,5】st.push(4);st.push(5);cout << st.size() << endl;  // 返回 栈 中的元素个数 -- 5个
}

💧swap 

将容器适配器(*this)的内容与 x 的内容进行交换,其实就是交换 两个栈 的元素数据 

 代码示例:

void test_stack()
{stack<int> st1;  // 构造一个栈 对象 --- 此时为空栈,底层为 dequest1.push(1);st1.push(2);st1.push(3);     // 向 栈 中插入 元素 【1,2,3】stack<int> st2;  // 构造一个栈 对象 --- 此时为空栈,底层为 dequest2.push(4);st2.push(5);st2.push(6);     // 向 栈 中插入 元素 【4,5,6】st1.swap(st2)   // 交换两个 栈 的数据// 遍历两个栈 while(!st1.empty()){cout << st1.top() << " ";    // 【6,5,4】st1.pop();  }while(!st2.empty()){cout << st2.top() << " ";    // 【3,2,1】st2.pop();  }}

  运行结果展示: 


三、queue 的详细解析

🔥 queue的介绍🔥

队列 【queue】是一种特殊的数结构,同时也是一种 容器适配器,遵循先进先出FIFO原则,其中从容器一端插入元素,另一端提取元素。主要操作:入队、出队、判断队空、查看队头队尾元素等;队列在原则上 是不允许进行 中部 的操作,这样会破坏队列的完整性。

从下图,可以看到 队列【queue】是作为容器适配器被实现,容器适配器对特定类封装作为其底层容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层。元素从队尾入列,从队头出列。(容器适配器本文的后面会详细讲解,这里先了解一下它 和 队列 的关系)

可以看出,队列也有两个模板参数

  • 参数1:T 栈中的元素类型,同时也是底层容器中的元素类型
  • 参数2:Container 实现栈时用到的底层容器,这里为缺省参数,缺省结构为 双端队列 deque

也就是说,【queue】底层容器可以是任何标准的容器类模板或者一些其特定的容器类,这些容器应该支持一下操作:

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

标准容器 vector、deque、list 均符合上面的这些要求,默认情况下,如果没有为 【queue】指定特定的顶层容器,默认情况下使用 deque (这一点会在本文,后下容器适配器,详细讲解)


🔥 queue的构造🔥

 它的构造方式如下:

 (1)使用默认的容器适配器构造一个 空队列

queue<int> q1;  // 默认底层容器为 deque 

 (2)使用其它的容器适配器构造一个 空队列

queue<int, vector<int>> q2;   // 显示实例化 底层容器为 vector
queue<int, list<int>> q2;     // 显示实例化,底层容器为 list

  代码示例:

#include <iostream>
#include<queue>
#include <vector>
#include <list>using namespace std;int main()
{queue<int> qDeque;	//默认使用 dequequeue<double, vector<double>> qVector;	//指定使用 vectorqueue<char, list<char>> qList;	//指定使用 listcout << typeid(qDeque).name() << endl;	//查看具体类型cout << typeid(qVector).name() << endl;cout << typeid(qList).name() << endl;return 0;
}

  运行结果展示: 


🔥 queue的常用接口🔥 

 相对于前面学习的内容,队列【queue】的接口更简单也更少,基本的使用函数如下:

💧push 

在队列末尾插入一个新元素,位于当前最后一个元素之后 

   代码示例:

void test_queue()
{queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);q.push(5);
}

💧size 

返回队列中元素的数量 

代码示例:

void test_queue()
{queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);q.push(5);cout << q.size() << endl;
}

   运行结果展示: 


💧front 

返回队列 的队头元素 

 代码示例:

void test_queue()
{queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);q.push(5);cout << q.front() << endl;
}

    运行结果展示: 


💧back 

返回队列中最后一个元素,也就是获取队尾元素 

代码示例: 

void test_queue()
{queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);q.push(5);cout << q.back() << endl;
}

 运行结果展示: 


💧pop  

删除队列中的下一个元素,有效地将其大小减少 1,也就是删除队头元素

代码示例: 

void test_queue()
{queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);q.push(5);q.pop(); // 删除队头元素cout << q.size() << endl;cout << q.front() << endl;
}

  运行结果展示: 


💧empty  

返回队列是否为空,即队列大小是否为 0

因为队列是先进先出,不支持遍历,所以这个接口可以用来实现队列遍历 

代码示例: 

void test_queue()
{queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);q.push(5);q.push(6);while (!q.empty()) {cout << q.front() << " ";q.pop();}}

 运行结果展示: 


💧swap   

将容器适配器(*this)的内容与 x 的内容切换,其实就是交换两个队列中的元素数据 

代码示例:  

void test_queue()
{queue<int> q1;q1.push(1);q1.push(2);q1.push(3);q1.push(4);q1.push(5);q1.push(6);queue<int> q2;q2.push(8);q2.push(9);q2.push(10);q1.swap(q2);while (!q1.empty()) {cout << q1.front() << " ";q1.pop();}while (!q2.empty()) {cout << q2.front() << " ";q2.pop();}
}

 运行结果展示: 


四、容器适配器 

🥝 什么是适配器 ?

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

从应用角度出发,STL 中的适配器可以分为三类: 

  • 容器适配器 container adapters
  • 迭代器适配器 iterator adapters
  • 仿函数适配器 functor adapters

其中,容器适配器 可修改底层为指定容器,如由 vector 构成的、由 list 构成的队列;迭代器适配器可以 实现其他容器的反向迭代器(后续介绍);最后的仿函数适配器就厉害了,几乎可以 无限制的创造出各种可能的表达式

本文介绍的是容器适配器,即  和 队列,最后还会介绍一下常作为这两种容器适配器的默认底层容器 双端队列

🍍stack 和 queue 的底层结构

虽然 【stack】和 【queue】中也可以存放元素,但是在 STL 中并没有将其划分在容器的行列,而是将其称为容器适配器 ,这是因为【stack】和 【queue】只是对其它容器的接口进行了包装,STL  中【queue】和 【stack】默认使用 【deque】比如:

注意: 容器支持 迭代器,但是容器适配器不支持迭代器,因为栈和队列这种数据结构不能随便去遍历,不然会导致发生变化,不易维护


🍇deque的原理介绍 

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

🍑deque 的底层结构

deque(双端队列)的底层结构通常由多个固定大小的缓冲区组成,每个缓冲区是一个连续的存储块。这些缓冲区通过一个指向前一个缓冲区和一个指向后一个缓冲区的指针进行连接,形成了一个双向链表。

deque的内部缓冲区以分块的形式存储元素。每个缓冲区有一个固定的大小,它通常是2的幂次方,例如512、1024等。缓冲区中的元素被存储在数组中,以保持元素的连续性。

deque的双向链表由一个或多个缓冲区组成,每个缓冲区都包含一个指向前一个缓冲区和一个指向后一个缓冲区的指针。第一个缓冲区的指向前一个缓冲区的指针为空指针,最后一个缓冲区的指向后一个缓冲区的指针也为空指针。

当需要在deque的头部或尾部插入或删除元素时,只涉及到相关缓冲区的操作,而不会涉及其他缓冲区。这种设计使得deque的插入和删除操作时间复杂度为常数级别(O(1))。

🍉deque 的优缺点 

⭕deque(双端队列)在大多数情况下是非常高效且灵活的数据结构,但它也有一些缺点需要注意。 

【vector】的优缺点:

  • 优点:适合尾插尾删,随机访问
  • 缺点:不适合头部或者中部插入删除,效率低,需要挪动数据;扩容有一定性能消耗,还可能存在一定程度的空间浪费。

【list】的优缺点:

  • 优点:在任意位置插入删除效率高;按需申请释放空间
  • 缺点:不支持随机访问;CPU高速缓存命中率低 

【deque】就结合了 【vector】和 【list】的优缺点而为之发明!!! 


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

【deque】 与 【list】相比较 的优势:其底层是连续空间,空间利用率较高,不需要存储额外字段

【deque】的致命缺陷:不适合遍历!!! 因为在遍历时,【deque】的迭代器要频繁的去检查其是否移动到某段空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑【vector】和 【list】。


🍈  选择 deque 的原因

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

【stack】是一种,后进先出的特殊线性数据结构,因此只要具有 push_back() pop_back() 操作的线性结构,都可以作为 【stack】的底层容器,比如 【vector】和 【list】都可以

【queue】是一种,先进先出的特殊线性数据结构,因此只要具有 push_back()pop_back() 操作的线性结构,都可以作为 【queue】的底层容器,比如 【list】

注意:string 、vector 不支持 头删,因此无法适配 queue


但是在 STL 中对 【stack】和 【queue】默认选择 【queue】作为其底层容器,原因为:

 【stack】 和 【queue】不需要遍历(因此stack 和 queue 没有迭代器),只需要在固定的一端或者两端进行操作。

在【satck】中元素增长时,【deque】比 【vector】的效率更高(扩容时不需要移动大量元素)

在【queue】中元素增长时,【deque】不仅效率高,而且内存使用率高

总结来说:【deque】结合了所有 【stack】 和 【queue】所需要的优点,而完美的避开了其缺陷


六、 模拟实现 【stack】和 【queue】

🔥 stack 的模拟实现🔥  

关于 stack 的模拟实现很简单,主要就是针对一些常用的接口,具体代码如下: 

namespace xas
{template<class T, class Container = deque<T>>class Stack{public:// 入栈void push(const T& x){_con.push_back(x);}// 出栈void pop(){_con.pop_back();}// 获取栈顶元素T& top(){return _con.back();}const T& top() const{return _con.back();}//获取栈中有效元素个数size_t size() const{return _con.size();}//判断栈是否为空bool empty() const{return _con.empty();}//交换两个栈中的数据void swap(Stack<T, Container>& st){_con.swap(st._con);}private:Container _con;};// 测试函数void test_stack(){Stack<int> st;st.push(1);st.push(2);st.push(3);st.push(4);st.push(5);st.push(6);cout << "栈中元素个数:" << st.size() << endl;cout << "出栈顺序:";while (!st.empty()) {cout << st.top() << " ";st.pop();}}
}

 测试结果:

适配器的厉害之处就在于 只要底层容器有我需要的函数接口,那么我就可以为其适配出一个容器适配器,比如 vector 构成的栈list 构成的栈deque 构成的栈,甚至是 string 也能适配出一个栈,只要符合条件,都可以作为栈的底层容器,当然不同结构的效率不同,因此库中选用的是效率较高的 deque 作为默认底层容器


🔥 queue 的模拟实现🔥  

关于 queue 的模拟实现很简单,主要就是针对一些常用的接口,具体代码如下:  

namespace xas
{template<class T, class Container = deque<T>>class Queue{public:// 入队void push(const T& x){_con.push_back(x);}// 出队void pop(){_con.pop_front();}// 获取队头元素T& front(){return _con.front();}const T& front() const{return _con.front();}// 获取队尾元素T& back(){return _con.back();}const T& back() const{return _con.back();}//获取队列中有效元素个数size_t size() const{return _con.size();}//判断队列是否为空bool empty() const{return _con.empty();}//交换两个栈中的数据void swap(Queue<T, Container>& q){_con.swap(q._con);}private:Container _con;};// 测试函数void test_queue(){Queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);q.push(5);q.push(6);q.push(7);cout << "队列中元素个数:" << q.size() << endl;cout << "出队顺序:";while (!q.empty()) {cout << q.front() << " ";q.pop();}}
}

  测试结果:


七、总结 

以上就是本篇关于 C++ STL学习之【stack和queue的详细概念和使用】的全部内容了,在本文中, 我们首先学习了 栈 和 队列 的基本概念和使用;其次学习了容器适配器,了解它存在的意义及种类;最后认识了容器适配器的默认底层容器 双端队列,见识了其复杂的结构设计及优缺点。

最后我们再来看一下栈 和 队列 在实际生活中的应用吧

栈的典型应用:

  • 浏览其中的后退与前进、软件中的撤销与反撤销。每当我们打开新的网页,浏览器就将上一个网页执行入栈,这样我们就可以通过【后退】操作来回倒上一页面,后退操作实际上是在执行出栈。如果同时支持后退和前进,那么则需要两个栈来配合。 
  • 程序内存管理。每当调用函数时,系统就会在栈顶添加一个栈帧,用来记录函数的上下文信息。在递归函数中,向上递推会不断执行入栈,向上回溯阶段时出栈。 

队列的典型应用: 

  • 淘宝订单。购物者下单后,订单就被加入到队列之中,随后系统再根据顺序依次处理队列中的订单。在双十一时,在短时间内会产生海量的订单,如何处理【高并发】则是工程师们需要重点思考的问题。

八、共勉 

以下就是我对 【stack和queue的详细概念和使用】 的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对 C++STL 的理解,请持续关注我哦!!!   

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

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

相关文章

Android文件路径获取

文件存储相关的文档 文件存储相关的系列文档如下&#xff0c;可根据需要查看这些文档 Android文件路径获取 Android存储权限梳理及api接口调用 Android各种存储路径的比较 Android R及以上版本中APP外部存储实现 Android文件路径获取 在Android开发中&#xff0c;经常需要…

24位DAC转换的FPGA设计及将其封装成自定义IP核的方法

在vivado设计中,为了方便的使用Block Desgin进行设计,可以使用vivado软件把自己编写的代码封装成IP核,封装后的IP核和原来的代码具有相同的功能。本文以实现24位DA转换(含并串转换,使用的数模转换器为CL4660)为例,介绍VIVADO封装IP核的方法及调用方法,以及DAC转换的详细…

REGX52.H报错

keil cannot open source input file "REGX52.H": No such file or directory 选择下面这个目录 Keil\C51\INC\Atmel

Hadoop-12-Hive 基本介绍 下载安装配置 MariaDB安装 3台云服务Hadoop集群 架构图 对比SQL HQL

章节内容 上一节我们完成了&#xff1a; Reduce JOIN 的介绍Reduce JOIN 的具体实现DriverMapperReducer运行测试 背景介绍 这里是三台公网云服务器&#xff0c;每台 2C4G&#xff0c;搭建一个Hadoop的学习环境&#xff0c;供我学习。 之前已经在 VM 虚拟机上搭建过一次&am…

无人机在航拍领域有哪些独特优势?

那肯定是便宜啊&#xff0c;相比传统的飞机或直升机航拍作业&#xff0c;无人机航拍具有更快的响应速度和更低的成本。无人机可以随时随地进行起降&#xff0c;并在短时间内完成航拍任务&#xff0c;极大地提高了作业效率。同时&#xff0c;无人机的运营成本相对较低&#xff0…

Mac如何杀毒?Mac电脑如何杀毒 mac杀毒软件推荐 mac杀毒软件哪个好用

Mac的轻薄和便携是众多白领选择它作为办公PC的原因&#xff0c;而除此之外&#xff0c;Mac另一个被人选择的原因&#xff0c;是macOS 系统特有的安全性。因此许多人以为&#xff0c;Mac不需要安装专门的杀毒软件。然而事实并非如此&#xff01; 每年都会出现许多恶意软件准们针…

昇思学习打卡-3-张量Tensor

本章节系统的学习了张量的相关内容&#xff0c;张量是由若干个当坐标系改变时满足转换关系的分量组成的集合。它是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数。是一种类似于矩阵的特殊的数据结构。包括 创建张量的方式&#xff1b;张量的属性&#…

解决:使用MySQL Command Line Client时光标不显示

问题描述: 使用MySQL Command Line Client时&#xff0c;命令行输入字符光标不显示, 如下图: 解决办法: 1.按Shift键将输入法切换至中文,打出中文: 2.再按一次Shift键,光标就会显示:

工作助手VB开发笔记(1)

1.思路 1.1 样式 样式为常驻前台的一个小窗口&#xff0c;小窗口上有三到四个按钮&#xff0c;为一级功能&#xff0c;是当前工作内容的常用功能窗口&#xff0c;有十个二级窗口&#xff0c;为选中窗口时的扩展选项&#xff0c;有若干后台功能&#xff0c;可选中至前台 可最…

antd+vue——实现table组件跨页多选,已选择数据禁止第二次重复选择

需求场景&#xff1a;点击【新增】按钮可以在分页弹窗中跨页多选选择数据后添加到页面中&#xff0c;再次点击【新增】&#xff0c;已经选择过的数据则置灰不让重复选择。 选择后&#xff0c;置灰 点击【确定】数据添加到页面中&#xff0c;可再次点击【新增】进行添加数据 …

项目上线文档编写指南

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

Ollama + Docker + AnythingLLM 搭建本地多用户AI知识库

整个过程需要准备三个工具&#xff1a; Ollama&#xff1a; 用于运行本地大模型的管理&#xff1a;llama3, qwen2等 Docker&#xff1a;用于运行AnythingLLM。 AnythingLLM&#xff1a;知识库运行平台&#xff0c;提供知识库构建及运行的功能。 Ollama, Docker 这二个安装不…

等保测评——云计算测评项2

安全计算环境-身份鉴别 当远程管理云计算平台中设备时&#xff0c;管理终端和云计算平台之间应建立双向身份验证机制&#xff1b; 远程管理云计算平台中的设备时&#xff0c;双向身份验证机制确保了管理终端和对端服务器的真实性&#xff0c;有效防止了重放攻击和DoS攻击,大大…

CGLib动态代理技术

基于CGLib的动态代理机制&#xff0c;ProxyFactoryy无需再像JDK动态代理那样实现一个interface&#xff0c;实际情况下可能这个interface并不存在&#xff0c;只需要实现另外一个接口MethodInterceptor即可 package com.hmdp.service.尚硅谷的代理模式3; //CGlib代理import …

AI大模型深度学习:理论与应用全方位解析

背景 在当前技术环境下&#xff0c;AI大模型学习不仅要求研究者具备深厚的数学基础和编程能力&#xff0c;还需要对特定领域的业务场景有深入的了解。通过不断优化模型结构和算法&#xff0c;AI大模型学习能够不断提升模型的准确性和效率&#xff0c;为人类生活和工作带来更多…

Xilinx FPGA:vivado实现乒乓缓存

一、项目要求 1、用两个伪双端口的RAM实现缓存 2、先写buffer1&#xff0c;再写buffer2 &#xff0c;在读buffer1的同时写buffer2&#xff0c;在读buffer2的同时写buffer1。 3、写端口50M时钟&#xff0c;写入16个8bit 的数据&#xff0c;读出时钟25M&#xff0c;读出8个16…

[图解]企业应用架构模式2024新译本讲解20-数据映射器2

1 00:00:01,860 --> 00:00:06,180 那么这个数据映射器因为它有这样的特点 2 00:00:07,310 --> 00:00:12,630 你想想&#xff0c;它负责同步这两边 3 00:00:13,010 --> 00:00:14,930 对象、数据库是独立的 4 00:00:15,990 --> 00:00:18,690 然后 5 00:00:18,700…

掌握MySQL基础命令:数据表结构修改详细操作

MySQL数据表&#xff08;Table&#xff09;是MySQL数据库中存储数据的基本结构单元。简单来说&#xff0c;数据表可以被看作是一个二维的、由行&#xff08;Row&#xff09;和列&#xff08;Column&#xff09;组成的表格&#xff0c;其中每一行代表了一个记录&#xff08;Reco…

Docker(二):Docker image Docker Container

本文将介绍 Docker 映像和容器以及 docker 文件之间的差异与联系&#xff0c;本文还将解释如何以及何时使用它们。 什么是 Dockerfile&#xff1f; 它是一个简单的文本文件&#xff0c;包含命令或过程的集合。我们运行的这些命令和准则作用于配置为创建新的 Docker 镜像的基本…

《长江信息通信》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《长江信息通信》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第一批认定学术期刊。 问&#xff1a;《长江信息通信》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;湖北省通信管理局 主办单位&#xff…