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

做业务需要知道哪些网站安阳县妇幼保健院

做业务需要知道哪些网站,安阳县妇幼保健院,wordpress数据库里面改端口,澄海网站建设公司stack前言 在上一篇文章中,我们首先提出了三个问题: C中stack 是容器么?stack 提供迭代器来遍历stack空间么?我们使用的STL中stack是如何实现的? 我们的回答是: stack不是容器,而是容器适配…

stack前言

在上一篇文章中,我们首先提出了三个问题:

  1. C++中stack 是容器么?
  2. stack 提供迭代器来遍历stack空间么?
  3. 我们使用的STL中stack是如何实现的?

我们的回答是:

  1. stack不是容器,而是容器适配器
  2. satck不提供迭代器来遍历stack空间。
  3. c++中,stack的底层实现默认使用deque。

在上一篇文章中有对这三个问题更详细地回答,并且有对deque底层实现的详细介绍。相信了解了deque之后对于学习stack会更有帮助!

deque(双端队列)底层实现和实际运用-CSDN博客

stack 在 deque 的基础上主要做了以下几件事情
 

  1. 限制了功能接口: stack 并没有实现自己的数据结构,而是适配了底层的容器(默认是 deque)。它只对外暴露了栈这种数据结构应该有的基本操作,强制执行了栈的后进先出 (LIFO) 的原则,隐藏了底层容器的许多其他功能
     
  2. 提供了更清晰的语义: 使用 stack 可以更清晰地表达代码的意图。当你看到代码中使用 stack 时,你会立即知道这里需要的是一个栈这种数据结构,而不是一个更通用的双端队列。这提高了代码的可读性和可维护性。

stack的函数接口

好消息:由于stack功能比较简单,所以stack提供的函数接口很少!!!

一定要注意:对于栈来说,是不向我们提供任何迭代器的,我们也就不能使用迭代器来遍历栈空间。

stack向我们提供的函数接口也比较少,常见的就是下面的几个:

  • top(): 返回栈顶元素的引用。
  • push(): 将一个新元素添加到栈顶,返回值类型: void。
  • pop(): 移除位于栈顶的元素,返回值类型: void。
  • empty(): 检查栈是否为空,空的时候返回true。
  • size(): 返回栈中当前元素的数量。

栈(stack)是容器适配器,容器适配器(stack/queue)中,添加元素函数名都是push,移除元素都是pop,在vector以及deque中函数名都是push_back,pop_back。

#include<iostream>//c++标准头文件,可以使用cout,cin等标准库函数 
#include<stack>//使用stack时需要的头文件 
using namespace std;//命名空间,防止重名给程序带来各种隐患,使用cin,cout,stack,map,set,vector,queue时都要使用
int main(){stack<int> s;//定义一个int类型的stacks.push(1);//往栈里放入一个元素1s.push(2);//往栈里放入一个元素2s.push(3); //往栈里放入一个元素3cout<<"按顺序放入元素1、2、3后,目前栈里的元素:1 2 3" <<endl;cout<<"s.size()="<<s.size()<<endl;//s.size()返回栈内元素的个数  cout<<"s.empty()="<<s.empty()<<endl; //判断栈是否为空,值为1代表空,0代表非空,用s.size()同样可以判断 ,s.size()的值为0就代表空的 cout<<"s.top()="<<s.top()<<endl;//查看栈顶的元素 cout<<endl;s.pop();//弹出栈顶元素 cout<<"s.pop()后,目前栈里的元素:1 2"<<endl;cout<<"s.size()="<<s.size()<<endl;cout<<"s.empty()="<<s.empty()<<endl; cout<<"s.top()="<<s.top()<<endl;cout<<endl;s.pop();cout<<"s.pop()后,目前栈里的元素:1"<<endl;cout<<"s.size()="<<s.size()<<endl;cout<<"s.empty()="<<s.empty()<<endl; cout<<"s.top()="<<s.top()<<endl;cout<<endl;s.pop();cout<<"s.pop()后,目前的栈是空的"<<endl;cout<<"s.size()="<<s.size()<<endl;cout<<"栈是空的就不能用s.top()访问栈顶元素了" <<endl; cout<<"s.empty()="<<s.empty()<<endl; }

运行结果: 

按顺序放入元素1、2、3后,目前栈里的元素:1 2 3
s.size()=3
s.empty()=0
s.top()=3s.pop()后,目前栈里的元素:1 2
s.size()=2
s.empty()=0
s.top()=2s.pop()后,目前栈里的元素:1
s.size()=1
s.empty()=0
s.top()=1s.pop()后,目前的栈是空的
s.size()=0
栈是空的就不能用s.top()访问栈顶元素了
s.empty()=1

stack实际运用

栈因其简单而强大的后进先出(LIFO) 特性,在计算机科学中扮演着重要的角色。无论是解决算法难题,还是作为构建更复杂数据结构的基础,栈都是一个非常有用的工具。下面介绍栈的常见的几种使用情景:

表达式求值 (Expression Evaluation):

  • 中缀表达式转后缀表达式 (Infix to Postfix Conversion): 栈可以用来存储操作符,并根据运算符优先级和括号来生成后缀表达式(也称为逆波兰表示法)。
  • 后缀表达式求值 (Postfix Evaluation): 栈可以用来存储操作数。当遇到操作符时,从栈中弹出所需数量的操作数进行计算,并将结果压回栈中。

括号匹配 (Parentheses Matching):

  • 判断一个字符串中的括号(例如 (), [], {}) 是否正确匹配。遍历字符串,遇到左括号则压入栈中,遇到右括号则检查栈顶是否是对应的左括号。如果匹配则弹出栈顶元素,否则或栈为空时遇到右括号则表示不匹配。最后栈为空则表示所有括号都匹配。

深度优先搜索 (Depth-First Search, DFS):

  • 在图或树的遍历中,DFS 通常使用栈(可以是显式的 std::stack,也可以是递归调用的隐式栈)来跟踪访问过的节点和待访问的邻居节点。比如对于二叉树的遍历中就是可以使用栈来实现二叉树的前序,中序,后序遍历。

回溯算法 (Backtracking):

  • 许多回溯算法(例如解决迷宫问题、N 皇后问题、子集生成等)都使用栈来保存当前的状态。当探索到一条死路时,可以从栈中弹出最近的状态进行回溯,尝试其他路径。

实现递归 (Implicitly):

  • 递归函数的执行本质上依赖于系统维护的函数调用栈。理解栈的工作方式有助于理解递归的原理。虽然你通常不会显式地用 std::stack 来“实现”递归,但你可以使用栈来将某些递归算法转换为迭代算法,以避免递归深度过大的问题。

深入探讨一下使用栈来实现递归

理论上来说,所有用递归能解决的问题都可以用栈(通常是通过迭代的方式模拟)来解决。

这是因为递归的本质就是通过系统维护的调用栈 (Call Stack) 来实现的。每次进行递归调用时,当前函数的局部变量、参数、返回地址等信息会被压入调用栈中。当递归调用返回时,这些信息会从栈中弹出,程序会回到上一次函数调用的位置继续执行。


 

实际上来说,递归方式的函数栈可以自动帮助我们来保存信息,保存的信息很有条理。

我们自己想用迭代+栈来实现的话,要考虑的问题就比较多,需要考虑

  • 何时入栈出栈,
  • 多次入栈出栈,
  • 还要考率栈为空时对应的逻辑,
  • 有的时候需要多个栈来实现简单递归就能实现的问题,
  • 不容易实现。

        虽然用迭代加栈来理解递归的本质很有帮助,但在实际开发中,我们通常会优先选择更自然、更易于理解和维护的实现方式。对于那些容易产生栈溢出的递归,或者对性能有极致要求的场景,才会考虑使用迭代加栈的方式进行优化或替代。

对于栈的一个问题解答

我们在了解完栈之后,可以显著发现栈的所有功能其实很简单,成员函数也不多,deque,vector的功能其实完全可以覆盖栈的功能,那为什么我们很多时候还是会选择使用栈呢?

从功能上讲,dequevector 的确可以用来模拟栈的行为。你可以只使用它们的尾部进行添加和删除操作,从而实现栈的 pushpop 功能。

然而,我们很多时候仍然选择使用 std::stack,这主要是出于以下几个重要的原因:

代码的意图和可读性 (Intent and Readability):

  • std::stack 这个名字本身就清晰地表明了代码的意图:这里需要一个后进先出 (LIFO) 的数据结构。当其他开发者(或者未来的你)阅读这段代码时,一眼就能明白这里使用的是栈的语义。
  • 如果你直接使用 dequevector 并只操作尾部,虽然功能上实现了栈,但代码的意图并不那么明确。可能会让人疑惑为什么选择 dequevector,是否还有其他操作会用到它们的其他功能。使用 std::stack 则消除了这种歧义。

制执行栈的语义 (Enforcing Stack Semantics):

  • std::stack 的接口被有意地限制为只包含栈的基本操作 (push, pop, top, empty, size, emplace, swap). 这种限制避免了开发者在不经意间使用了底层容器的其他功能(比如 dequepush_front, pop_front, 随机访问等,或者 vector 的随机访问),从而破坏了栈的 LIFO 原则。

综合来看:使用 stack 更多的是出于代码清晰性语义明确性强制执行栈原则以及提高代码可维护性的考虑。它是一种更符合逻辑和更安全的选择,能够更好地表达程序的意图。

queue前言

在了解完 stack 之后,我们现在来看一下 queue。首先提出三个类似的问题:

  1. C++ 中 queue 是容器么?
  2. queue 提供迭代器来遍历 queue 空间么?
  3. 我们使用的 STL 中 queue 是如何实现的?

我们的回答是:

  1. queue 不是容器,而是容器适配器。
  2. queue 不提供迭代器来遍历 queue 空间。
  3. C++ 中,queue 的底层实现默认使用 deque。

 在上一篇文章中有对这三个问题更详细地回答,并且有对deque底层实现的详细介绍。相信了解了deque之后对于学习queue会更有帮助!

deque(双端队列)底层实现和实际运用-CSDN博客

queue 在 deque 的基础上主要做了以下几件事情:

  • 限制了功能接口: queue 并没有实现自己的数据结构,而是适配了底层的容器(默认是 deque)。它只对外暴露了队列这种数据结构应该有的基本操作,强制执行了队列的先进先出 (FIFO) 的原则,而隐藏了底层容器的许多其他功能
  • 提供了更清晰的语义: 使用 queue 可以更清晰地表达代码的意图。当你看到代码中使用 queue 时,你会立即知道这里需要的是一个队列这种数据结构,而不是一个更通用的双端队列。这提高了代码的可读性和可维护性。

queue的函数接口

和stack(栈)一样,queue也是一个容器适配器,所以queue也是不向我们提供任何迭代器的,我们也就不能使用迭代器来遍历队列空间。

queue向我们提供的函数接口也比较少,常见的就是下面的几个:

  • front(): 返回队列头部元素的引用。
  • back(): 返回队列尾部元素的引用。
  • push(): 将一个新元素添加到队列的尾部,返回值类型: void。
  • pop(): 移除位于队列头部的元素,返回值类型: void。
  • empty(): 检查队列是否为空,空的时候返回true。
  • size(): 返回队列中当前元素的数量。

 队列(queue)是容器适配器,容器适配器(stack/queue)中,添加元素函数名都是push,移除元素都是pop,在vector以及deque中函数名都是push_back,pop_back。

queue实际运用

queue 在实际算法编程中有着广泛的应用,其核心特性是先进先出 (FIFO),这使得它非常适合处理需要按顺序处理元素的场景。以下是一些常见的运用:

1. 广度优先搜索 (Breadth-First Search, BFS):(最常见也是最重要的应用

  • 典型场景: 在无权图中查找两个节点之间的最短路径。
  • 原理: BFS 从起始节点开始,首先访问其所有直接邻居,然后访问这些邻居的邻居,依此类推,逐层扩展。std::queue 非常适合用来存储待访问的节点,保证了按层级顺序进行探索。

2. 树的层序遍历 (Level Order Traversal):

  • 典型场景: 按照树的层级顺序访问所有节点。
  • 原理: 将根节点入队,然后当队列不为空时,取出队首节点并访问它,接着将其所有子节点按从左到右的顺序入队。重复这个过程,直到队列为空。

3. 任务调度 (Task Scheduling):

  • 典型场景: 模拟任务按照到达顺序被处理的情况。
  • 原理: 将待处理的任务放入队列中,然后按照入队顺序依次取出任务进行处理。这保证了先到达的任务先被执行。

4. 消息队列 (Message Queues):

  • 典型场景: 在不同的程序或线程之间传递消息。
  • 原理: 发送者将消息放入队列,接收者从队列中取出消息进行处理。队列保证了消息的顺序性和可靠性。虽然实际的消息队列系统可能更复杂,但 std::queue 提供了一个基本的模型。

对比一下stack和queue

函数接口方面

queue中的函数接口和stack中的差不多,stack常用的函数接口有5个,queue常用的函数接口有6个。

  • stack中返回栈顶元素是top();
  • queue中返回队列头部元素的引用是front(),返回队列尾部元素的引用时back()。

  • stack将一个新元素添加到栈顶函数接口为push(),将一个元素从栈顶移除的接口为pop();
  • queue将一个新元素添加到队列尾部函数接口为push(),将一个元素从队列头部移除的接口为pop()。

对于empty() 和 size()这两个函数接口来说,stack和queue使用方法一样。

容器适配器功能方面:

这两个容器适配器默认的底层实现使用的都是deque(双端队列)

STL标准库对于stack和queue来说,都没有提供迭代器来对其进行访问。

stack是对同一个口进行push和pop操作,queue是对两个口中的尾部进行push操作,对头部进行pop操作。

http://www.dtcms.com/wzjs/587202.html

相关文章:

  • 网站如何做伪静态页面小型教育网站开发与设计
  • 温州捷创网站建设宜良县建设局网站
  • 网站在建设中页面安阳网站建设报价
  • 汕头免费模板建站游戏公司官方网站模版
  • 怎么关闭自己公司网站网站建设的基本要求
  • 网站批量发布重庆网络公司做什么生意好
  • 响应式网站项目大宗商品一览表
  • 做网站和做程序一样吗上海短视频seo优化网站
  • 用路由器做网站网络推广培训机构
  • 有做敦煌网站的吗微信公众号编辑教程
  • 网站建设的途径山东做网站建设的好公司哪家好
  • 怎么做网站黑链中企动力企业
  • 网站霸屏怎么做建设英文网站的申请怎么写
  • 重庆网站seo外包网站后台不能上传
  • 网站建设 m.ykn.ccwordpress 重新安装
  • 做网站需要知道什么软件煎蛋wordpress二次开发
  • 湖南省建设工程造价管理总站网站利用ps制作网站的设计
  • 网站建设的语言长春网络推广公司小技巧
  • 途牛旅游网站建设方案注册资金100万的公司要多少钱
  • asp 做网站的缺点唐山企业网站建设
  • 网站建设中的板块名称站长网站大全
  • 宜宾市做网站多少钱开封网站优化
  • 遵义城乡住房建设厅网站有网站源码 怎么建设网站
  • 域名价格查询网站单位网页制作
  • php语言的网站建设上海小程序开发哪家好
  • 微信菜单栏那些网站怎么做做网站公司排名是什么
  • 网站开发工资高嘛服务行业做网站
  • 国外网站做淘宝客四川网站建设平台
  • 好的网站优化公司WordPress网站打不开nginx
  • 做性的网站有哪些内容安卓做网站教程