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

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

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

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

  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等问题。同时,栈在系统级编程(如调用栈)中也扮演着重要角色。掌握栈的实现和应用,是提升算法能力和编程水平的关键。

相关文章:

  • Java里int和Integer的区别?
  • 【第10章:自然语言处理高级应用—10.4 NLP领域的前沿技术与未来趋势】
  • 基于SpringBoot的医院药房管理系统【源码+答辩PPT++项目部署】高质量论文1-1.5W字
  • 掌握SQLite_轻量级数据库的全面指南
  • python的类装饰器
  • 前端与后端的对接事宜、注意事项
  • FRRouting配置与OSPF介绍,配置,命令,bfd算法:
  • SpringBoot+数据可视化的奶茶点单购物平台(程序+论文+讲解+安装+调试+售后)
  • 【PostgreSQL】PG在windows下的安装
  • Linux 网络设备驱动中的 netdev_priv 函数详解
  • 【学习笔记】深度学习网络-深度模型中的优化
  • 垃圾回收器
  • Spring——Spring开发实战经验(1)
  • trl-强化学习训练-grpo训练为例
  • 网络接收的流程理解
  • [NKU]C++基础课(二)--- externC、强制类型转换、类与对象、面向对象程序设计语言、对象创建和使用、类的定义、封装
  • java死锁
  • 轮子项目--消息队列的实现(4)
  • openharmony系统移植之显示驱动框架从framebuffer升级为drm(linux-5.10)
  • 【Java】—— 包装类泛型
  • 欧洲理事会前主席米歇尔受聘中欧国际工商学院特聘教授,上海市市长龚正会见
  • 保利42.41亿元竞得上海杨浦东外滩一地块,成交楼面单价超8万元
  • 纽约大学朗格尼医学中心的转型带来哪些启示?
  • 司法部:加快研究制定行政执法监督条例,建立完善涉企行政执法监督长效机制
  • 深入贯彻中央八项规定精神学习教育中央第六指导组指导督导中国工商银行见面会召开
  • 上海:5月8日起5年以上首套个人住房公积金贷款利率下调至2.6%