栈的深度解析:从基础实现到高级算法应用——C++实现与实战指南

news2025/3/12 12:38:25

一、栈的核心算法与应用场景

栈的先进后出特性使其在以下算法中表现优异:

  1. 括号匹配:校验表达式合法性。
  2. 表达式求值:中缀转后缀,逆波兰表达式求值。
  3. 深度优先搜索(DFS):模拟递归调用。
  4. 单调栈:解决区间最值问题。
  5. 函数调用栈:模拟程序执行流程。

二、括号匹配算法

1. 问题描述

给定一个包含()[]{}的字符串,判断其是否合法。

2. 实现代码
#include <stack>
#include <string>
#include <unordered_map>

bool isValidParentheses(const std::string& s) {
    std::stack<char> stack;
    std::unordered_map<char, char> mapping = {
        {')', '('},
        {']', '['},
        {'}', '{'}
    };

    for (char ch : s) {
        if (mapping.count(ch)) { // 右括号
            if (stack.empty() || stack.top() != mapping[ch]) {
                return false;
            }
            stack.pop();
        } else { // 左括号
            stack.push(ch);
        }
    }
    return stack.empty();
}
3. 关键点
  • 使用哈希表存储括号映射关系。
  • 栈为空时遇到右括号直接返回false
  • 最终栈为空才表示匹配成功。

三、表达式求值算法

1. 中缀转后缀(逆波兰表达式)
#include <stack>
#include <string>
#include <vector>
#include <cctype>

std::vector<std::string> infixToPostfix(const std::string& expr) {
    std::vector<std::string> output;
    std::stack<char> operators;
    std::unordered_map<char, int> precedence = {
        {'+', 1}, {'-', 1},
        {'*', 2}, {'/', 2},
        {'^', 3}
    };

    for (size_t i = 0; i < expr.size(); ++i) {
        char ch = expr[i];
        if (isdigit(ch)) { // 数字直接输出
            std::string num;
            while (i < expr.size() && isdigit(expr[i])) {
                num += expr[i++];
            }
            output.push_back(num);
            --i;
        } else if (ch == '(') { // 左括号入栈
            operators.push(ch);
        } else if (ch == ')') { // 右括号弹出至左括号
            while (!operators.empty() && operators.top() != '(') {
                output.push_back(std::string(1, operators.top()));
                operators.pop();
            }
            operators.pop(); // 弹出左括号
        } else { // 运算符
            while (!operators.empty() && precedence[ch] <= precedence[operators.top()]) {
                output.push_back(std::string(1, operators.top()));
                operators.pop();
            }
            operators.push(ch);
        }
    }

    // 弹出剩余运算符
    while (!operators.empty()) {
        output.push_back(std::string(1, operators.top()));
        operators.pop();
    }

    return output;
}
2. 逆波兰表达式求值
#include <stack>
#include <vector>
#include <string>

int evalRPN(const std::vector<std::string>& tokens) {
    std::stack<int> stack;
    for (const std::string& token : tokens) {
        if (token == "+" || token == "-" || token == "*" || token == "/") {
            int b = stack.top(); stack.pop();
            int a = stack.top(); stack.pop();
            if (token == "+") stack.push(a + b);
            else if (token == "-") stack.push(a - b);
            else if (token == "*") stack.push(a * b);
            else stack.push(a / b);
        } else {
            stack.push(std::stoi(token));
        }
    }
    return stack.top();
}

四、单调栈算法

1. 问题描述

给定一个数组,找到每个元素的下一个更大元素(Next Greater Element)。

2. 实现代码
#include <stack>
#include <vector>

std::vector<int> nextGreaterElements(const std::vector<int>& nums) {
    std::vector<int> result(nums.size(), -1);
    std::stack<int> stack;

    for (int i = 0; i < nums.size(); ++i) {
        while (!stack.empty() && nums[stack.top()] < nums[i]) {
            result[stack.top()] = nums[i];
            stack.pop();
        }
        stack.push(i);
    }

    return result;
}
3. 关键点
  • 栈中存储数组下标,便于更新结果。
  • 时间复杂度为O(n),空间复杂度为O(n)。

五、深度优先搜索(DFS)与栈

1. 递归DFS
void dfsRecursive(Node* node) {
    if (!node) return;
    // 处理当前节点
    for (auto child : node->children) {
        dfsRecursive(child);
    }
}
2. 迭代DFS(使用栈)
void dfsIterative(Node* root) {
    if (!root) return;
    std::stack<Node*> stack;
    stack.push(root);

    while (!stack.empty()) {
        Node* curr = stack.top();
        stack.pop();
        // 处理当前节点
        for (auto it = curr->children.rbegin(); it != curr->children.rend(); ++it) {
            stack.push(*it); // 子节点逆序压栈
        }
    }
}

六、函数调用栈模拟

1. 问题描述

模拟函数调用栈的行为,实现一个简单的解释器。

2. 实现代码
#include <stack>
#include <string>
#include <iostream>

void executeFunction(const std::string& name) {
    std::cout << "Entering function: " << name << std::endl;
    // 模拟函数执行
    std::cout << "Exiting function: " << name << std::endl;
}

void simulateCallStack() {
    std::stack<std::string> callStack;
    callStack.push("main");
    executeFunction(callStack.top());

    callStack.push("func1");
    executeFunction(callStack.top());

    callStack.push("func2");
    executeFunction(callStack.top());

    while (!callStack.empty()) {
        callStack.pop();
        if (!callStack.empty()) {
            std::cout << "Returning to function: " << callStack.top() << std::endl;
        }
    }
}

七、总结

栈作为一种基础数据结构,在算法设计中具有广泛的应用。通过深入理解栈的特性和应用场景,可以高效解决括号匹配、表达式求值、单调栈、DFS等问题。同时,栈在系统级编程(如调用栈)中也扮演着重要角色。掌握栈的实现和应用,是提升算法能力和编程水平的关键。

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

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

相关文章

IDEA集成DeepSeek

引言 随着数据量的爆炸式增长&#xff0c;传统搜索技术已无法满足用户对精准、高效搜索的需求。 DeepSeek作为新一代智能搜索技术&#xff0c;凭借其强大的语义理解与深度学习能力&#xff0c;正在改变搜索领域的游戏规则。 对于 Java 开发者而言&#xff0c;将 DeepSeek 集成…

leetcode:627. 变更性别(SQL解法)

难度&#xff1a;简单 SQL Schema > Pandas Schema > Salary 表&#xff1a; ----------------------- | Column Name | Type | ----------------------- | id | int | | name | varchar | | sex | ENUM | | salary | int …

SQLMesh系列教程-3:SQLMesh模型属性详解

SQLMesh 的 MODEL 提供了丰富的属性&#xff0c;用于定义模型的行为、存储、调度、依赖关系等。通过合理配置这些属性&#xff0c;可以构建高效、可维护的数据管道。在 SQLMesh 中&#xff0c;MODEL 是定义数据模型的核心结构&#xff0c;初学SQLMesh&#xff0c;定义模型看到属…

【Leetcode 952】按公因数计算最大组件大小

题干 给定一个由不同正整数的组成的非空数组 nums &#xff0c;考虑下面的图&#xff1a; 有 nums.length 个节点&#xff0c;按从 nums[0] 到 nums[nums.length - 1] 标记&#xff1b;只有当 nums[i] 和 nums[j] 共用一个大于 1 的公因数时&#xff0c;nums[i] 和 nums[j]之…

【第4章:循环神经网络(RNN)与长短时记忆网络(LSTM)— 4.6 RNN与LSTM的变体与发展趋势】

引言:时间序列的魔法钥匙 在时间的长河中,信息如同涓涓细流,绵延不绝。而如何在这无尽的数据流中捕捉、理解和预测,正是循环神经网络(RNN)及其变体长短时记忆网络(LSTM)所擅长的。今天,我们就来一场深度探索,揭开RNN与LSTM的神秘面纱,看看它们如何在时间序列的海洋…

简单几个步骤完成 Oracle 到金仓数据库(KingbaseES)的迁移目标

作为国产数据库的领军选手&#xff0c;金仓数据库&#xff08;KingbaseES&#xff09;凭借其成熟的技术架构和广泛的市场覆盖&#xff0c;在国内众多领域中扮演着至关重要的角色。无论是国家电网、金融行业&#xff0c;还是铁路、医疗等关键领域&#xff0c;金仓数据库都以其卓…

八、SPI读写XT25数据

8.1 SPI 简介 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外设接口&#xff09;是一种同步串行通信协议&#xff0c;广泛用于嵌入式系统中连接微控制器与外围设备&#xff0c;如传感器、存储器、显示屏等。 主要特点 1. 全双工通信&#xff1a;支持同时发送…

Visionpro 齿轮测量

效果展示 一、题目要求 求出最大值&#xff0c;最小值&#xff0c;平均值 二、分析 1.首先要进行模板匹配 2.划清匹配范围 3.匹配小三角的模板匹配 4.卡尺 5.用找圆工具 工具 1.CogPMAlignTool 2.CogCaliperTool 3.CogFindCircleTool 4.CogFixtureTool 三、模板匹…

索引以及索引底层数据结构

一、什么是索引&#xff1f; 索引&#xff08;index&#xff09;是数据库高效获取数据的数据结构&#xff08;有序&#xff09;。在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff08;B树&#xff09;&#xff0c;这些数据结构以某种方式指向真在…

开业盛典活动策划方案拆解

道叔来给大家详细剖析咱们方案库里刚收录的这份《蜀大侠火锅店武侠风开业盛典活动策划方案》了&#xff0c;保证让你看完直呼过瘾&#xff0c;收获满满&#xff01; 一、主题创意&#xff1a;武侠风&#xff0c;直击人心 首先&#xff0c;咱们得夸一下这活动的主题——“XXX‘…

API 接口自动化

HTTP协议 - 白月黑羽 HTTP协议简介 如果客户端是浏览器&#xff0c;如何在chrome浏览器中查看 请求和响应的HTTP消息&#xff1f;按f12-》network 清除当前信息 响应的消息体在Response里看 点preview&#xff0c;可以看响应的消息体展开的格式 HTTP请求消息 请求头 reques…

安全测试|SSRF请求伪造

前言 SSRF漏洞是一种在未能获取服务器权限时&#xff0c;利用服务器漏洞&#xff0c;由攻击者构造请求&#xff0c;服务器端发起请求的安全漏洞&#xff0c;攻击者可以利用该漏洞诱使服务器端应用程序向攻击者选择的任意域发出HTTP请求。 很多Web应用都提供了从其他的服务器上…

智能编程助手功能革新与价值重塑之:GitHub Copilot

引言&#xff1a; GitHub Copilot 的最新更新为开发者带来了显著变化&#xff0c;其中 Agent Mode 功能尤为引人注目。该模式能够自动识别并修复代码错误、自动生成终端命令&#xff0c;并具备多级任务推理能力&#xff0c;这使得开发者在开发复杂功能时&#xff0c;可大幅减少…

物联网行业通识:从入门到深度解析

物联网行业通识&#xff1a;从入门到深度解析 &#xff08;图1&#xff1a;物联网生态示意图&#xff09; 一、引言&#xff1a;万物互联时代的到来 根据IDC最新预测&#xff0c;到2025年全球物联网设备连接数将突破410亿&#xff0c;市场规模达1.1万亿美元。物联网&#xff…

ABP - 事件总线之分布式事件总线

ABP - 事件总线之分布式事件总线 1. 分布式事件总线的集成1.2 基于 RabbitMQ 的分布式事件总线 2. 分布式事件总线的使用2.1 发布2.2 订阅2.3 事务和异常处理 3. 自己扩展的分布式事件总线实现 事件总线可以实现代码逻辑的解耦&#xff0c;使代码模块之间功能职责更清晰。而分布…

再谈SpringCloud Gateway源码

再谈SpringCloud Gateway源码 一、整体请求流程二、前置对象准备1、实例化HandlerMapping2、实例化Route3、实例化WebHandler 三、实践业务扩展点1、定义扩展Route对象2、Filter能做什么3、定义扩展Filter对象4、定义父类Filter简化请求参数处理 前言&#xff1a; 之前有阅读过…

把 CSV 文件摄入到 Elasticsearch 中 - CSVES

在我们之前的很多文章里&#xff0c;我有讲到这个话题。在今天的文章中&#xff0c;我们就提重谈。我们使用一种新的方法来实现。这是一个基于 golang 的开源项目。项目的源码在 https://github.com/githubesson/csves/。由于这个原始的代码并不支持 basic security 及带有安全…

C进阶 数据的存储

目录 前言 一&#xff0c;VS的知识储备 二&#xff0c;有趣的scanf()读取 三&#xff0c;数据的存储 引言 四&#xff0c;整数存储 五&#xff0c;小数存储 总结 前言 这里将深入计算机&#xff0c;看计算机是如何进行数据的存储的&#xff0c;怎么在计算机里面筑巢 为…

【c++】【Linux】【进程】线程终止/崩溃 会导致进程终止/崩溃 吗?

【c】【Linux】【进程】线程终止/崩溃 会导致进程终止/崩溃 吗&#xff1f; 1.线程终止会导致进程终止吗&#xff1f; 在操作系统中&#xff0c;线程是进程的基本执行单元&#xff0c;一个进程可以包含一个或多个线程。 当一个子线程终止时&#xff0c;进程并不会因此自动终…

springcloud集成gateway

本篇文章只介绍gateway模块的搭建步骤&#xff0c;并无gateway详细介绍 gateway详解请查看&#xff1a;SpringCloudGateway官方文档详解 前置处理 父模块中已指定版本 不知道如何选择版本看这篇&#xff1a; 手把手教你梳理springcloud与springboot与springcloudalibaba的版本…