C++数据结构:栈和队列的应用

news/2024/11/23 17:02:30/

文章目录

  • 前言
  • 一、栈是什么?
    • 逆波兰表达式(RPN)
  • 二、队列是什么?
    • BFS搜索
  • 总结


前言

C++ 是一种面向对象的编程语言,它提供了多种数据结构,前面文章已介绍过数组、链表、hash表,并用自己的方法实现。用于存储和操作数据的结构在STL中还有很多,其中两种常用的数据结构是栈和队列。本文将介绍栈和队列的概念,特点,实现方式和应用场景。


一、栈是什么?

栈是一种后进先出(LIFO)的数据结构,它只允许在一端(称为栈顶)进行插入和删除操作。栈可以用数组或链表来实现。C++ 标准库中提供了一个模板类 std::stack,可以方便地创建和使用栈对象。栈的基本操作有:

  • push(x):将元素 x 压入栈顶。
  • pop():弹出并返回栈顶元素。
  • top():返回栈顶元素,但不弹出。
  • empty():判断栈是否为空。
  • size():返回栈中元素的个数。

栈的应用场景有:

  • 函数调用:当一个函数被调用时,它的参数,局部变量和返回地址都会被压入系统栈中,当函数返回时,它们会被弹出。这样可以实现函数的嵌套调用和递归调用。
  • 表达式求值:当遇到一个算术或逻辑表达式时,可以用一个操作数栈和一个操作符栈来辅助求值。遇到操作数时,压入操作数栈;遇到操作符时,如果操作符栈为空或者当前操作符的优先级高于栈顶操作符的优先级,则压入操作符栈;否则,弹出操作符栈的栈顶元素,并从操作数栈中弹出两个元素,进行相应的计算,并将结果压入操作数栈,重复此过程直到遇到表达式结束符或操作符栈为空,最后从操作数栈中弹出最终结果。
  • 括号匹配:当遇到一个包含括号的字符串时,可以用一个栈来检查括号是否匹配。遇到左括号时,压入栈;遇到右括号时,如果栈为空或者栈顶元素与右括号不匹配,则说明括号不匹配;否则,弹出栈顶元素,重复此过程直到字符串结束或者栈为空,最后如果栈为空,则说明括号匹配。

逆波兰表达式(RPN)

例如每日一练中的逆波兰表达式(RPN)。RPN是一种不需要括号的数学表达式,它使用操作符后置的方式来表示运算顺序。例如,表达式 2 + 3 * 4 可以写成 2 3 4 * +。为了计算RPN表达式,我们可以使用一个栈来存储操作数和操作符。每当遇到一个操作数,我们就把它压入栈中;每当遇到一个操作符,我们就从栈中弹出两个操作数,进行相应的运算,并把结果压入栈中。最后,栈中剩下的元素就是表达式的值:

#include <iostream>
#include <string>
#include <stack>
#include <sstream>using namespace std;
int solution(int n, std::string arr){int result;// TODO:stringstream ss(arr);stack<int> s;                      //创建一个空栈string input;                      //输入的字符串while (ss >> input){if (input == "+"){             //如果输入是加号int a = s.top(); s.pop();   //弹出栈顶操作数int b = s.top(); s.pop();    s.push(a + b);               //把两个操作数相加的结果压入栈中} else if (input == "-"){       //如果输入是减号int a = s.top(); s.pop(); int b = s.top(); s.pop(); s.push(b - a); } else if (input == "*"){      //如果输入是乘号int a = s.top(); s.pop(); int b = s.top(); s.pop(); s.push(a * b); } else if (input == "/"){      //如果输入是除号int a = s.top(); s.pop(); int b = s.top(); s.pop(); s.push(b / a);    } else {                    //如果输入是其他字符,认为是一个整数s.push(std::stoi(input));    //把输入转换成整数并压入栈中}}result = s.top();       //输出最终结果return result;
}int main() {int n;std::string arr = "3 4 - 5 +";int result = solution(n, arr);std::cout<<result<<std::endl;return 0;
}

二、队列是什么?

队列是一种先进先出(FIFO)的数据结构,它只允许在一端(称为队尾)进行插入操作,在另一端(称为队首)进行删除操作。队列可以用数组或链表来实现。C++ 标准库中提供了一个模板类 std::queue,可以方便地创建和使用队列对象。队列的基本操作有:

  • push(x):将元素 x 插入队尾。
  • pop():弹出并返回队首元素。
  • front():返回队首元素,但不弹出。
  • back():返回队尾元素,但不插入。
  • empty():判断队列是否为空。
  • size():返回队列中元素的个数。

队列的应用场景有:

  • 缓冲区:当有多个生产者和消费者同时对同一资源进行访问时,可以用一个队列来作为缓冲区,保证生产者和消费者之间的同步和互斥。生产者将生产的数据插入队尾,消费者从队首取出数据进行消费。
  • 广度优先搜索:当需要对一个图或者树进行遍历时,可以用一个队列来辅助实现广度优先搜索(BFS)。首先将起始节点插入队列,然后循环执行以下步骤:从队首取出一个节点,并访问它;将该节点的所有未访问过的邻居节点插入队尾;重复此过程直到队列为空或者找到目标节点。
  • 线程池:当有多个任务需要执行时,可以用一个队列来存储任务,并创建一定数量的线程来执行任务。每个线程从队首取出一个任务,并执行它;如果任务执行完毕,则再从队首取出下一个任务;如果任务执行过程中发生异常,则将任务重新插入队尾;重复此过程直到队列为空或者线程终止。

BFS搜索

下面是一个使用C++和队列(queue)实现的简单BFS搜索例子:

#include <iostream>
#include <queue>
using namespace std;int main(){queue<int> q;int graph[4][4] = {{0, 1, 1, 0},{0, 0, 1, 0},{1, 0, 0, 1},{0, 0, 0, 1}};bool visited[4] = {false};q.push(0);visited[0] = true;while (!q.empty()){int v = q.front();q.pop();cout << v << " ";for (int i = 0; i < 4; i++){if (graph[v][i] == 1 && !visited[i]){q.push(i);visited[i] = true;}}}return 0;
}

上面的代码中,我们定义了一个二维数组graph来表示图。graph[i][j]为1表示顶点i和顶点j之间有一条边。我们还定义了一个布尔数组visited来记录每个顶点是否已经被访问过。

在函数中,我们首先将起始顶点(顶点0)加入队列,并将其标记为已访问。然后,我们进入一个循环,直到队列为空。在每次循环中,我们从队列的前端取出一个顶点v,并输出它。接着,我们遍历与顶点v相邻的所有顶点,如果这些顶点尚未被访问过,则将它们加入队列,并将它们标记为已访问。


总结

总之,C++ 栈和队列是两种常用的数据结构,它们有各自的特点和适用场景。掌握它们的概念,特点,实现方式和应用场景,对于提高编程能力和解决实际问题都有很大帮助。

栈和队列的实现比较容易,用数组就能模拟一个,这里就简单的介绍了一下如何灵活使用。至此就写完了常用的C++内置数据结构了,以后再写树和图。


http://www.ppmy.cn/news/101858.html

相关文章

Qt编程基础 | 第六章-窗体 | 6.2、VS导入资源文件

一、VS导入资源文件 1.1、导入资源文件 步骤一&#xff1a; 将所有图片放到各自文件夹下&#xff0c;并将文件夹拷贝到资源文件&#xff08;.qrc文件&#xff09;的同级目录下&#xff0c;如下&#xff1a; 步骤二&#xff1a; 新建VS项目的时候&#xff0c;系统会自动建好一…

Vue组件化、通过自定义指令子组件向父组件传递

1.如何安装Vue脚手架&#xff1f; 第一步&#xff08;仅第一次执行&#xff09;&#xff1a;全局安装vue/clinpm install -g vue/cli 第二步&#xff1a;切换到你要创建项目的目录&#xff0c;然后使用命令创建项目vue create xxxx 第三步&#xff1a;启动项目npm run serve 2…

网络货运系统源码 网络货运平台源码,货运APP源码 货物运输管理源码

网络货运系统源码 网络货运平台源码&#xff0c;货运APP源码 货物运输管理源码 网络货运为无车承运人更名而来&#xff0c;网络货运平台的好处可以节省找车找货的时间与成本。根据国家对智慧物流行业的发展规划&#xff0c;及《网络平台道路货物运输经营管理办法》等相关法律法…

VB一个可以改变箭头方向的气泡提示

新建一个类名。名称为clsTip Option Explicit * 模块名称&#xff1a;clsTip.cls * 功能&#xff1a;一个可以改变箭头方向的气泡提示类 Private Type TOOLINFO cbSize As Long dwFlags As Long hwnd As Long dwID As Long rtRect(3) As Long hInst As Long lpszText As String…

【MLC】 TensorIR 练习

文章目录 前言TensorIR 练习TensorIR: 张量程序抽象案例研究练习 1&#xff1a;广播加法练习 2&#xff1a;二维卷积练习 3&#xff1a;变换批量矩阵乘法程序 总结 前言 这两天重新看了一下天奇的mlc课程文档&#xff0c;把里边儿的TensorIR 练习写了一下&#xff0c;顺便推广…

中低压母线室弧光保护装置在水电站的应用

摘要&#xff1a;本文介绍了电弧光保护在水电站的配置及应用&#xff0c;提供给相关人员参考。 关键词&#xff1a;水电站&#xff1b;开关柜&#xff1b;电弧光 0前言 电弧光是由于发生相间短路或接地短路时空气电离而形成的。在我国电力系统中开关柜内部电弧光故障时有发生…

华为OD机试真题 Java 实现【基站维修工程师】【2023Q1 200分】,附详细解题思路

一、题目描述 小王是一名基站维护工程师,负责某区域的基站维护。 某地方有n个基站(1<n<10),已知各基站之间的距离s(0<s<500),并且基站x到基站y的距离,与基站y到基站x的距离并不一定会相同。 小王从基站1出发,途径每个基站1次,然后返回基站1,需要请你…

【SonarQube】下载、安装、配置、使用介绍

文章目录 SonarQube安装运行使用root启动问题处理修改文件数限制JDK版本问题创建Project创建token扫描代码数据持久化在线文档 SonarQube安装 官网下载地址: http://www.sonarqube.org/downloads/9.9.1.69595下载地址: https://binaries.sonarsource.com/Distribution/sonarqu…