C++中栈结构建立与操作详细解析

C++中栈结构建立与操作详细解析

什么是栈?

栈(stack)是一种特殊的数据结构,它只允许在一个端口进行插入和删除操作。这个端口常被称为栈顶(top)。栈的正常操作是先进后出(LIFO),也就是说后进入的元素会先被弹出。

举个例子,假设我们将一叠盘子放在桌子上,每新洗好一个盘子,我们就把它放在盘子栈的顶端。当我们需要取出盘子时,我们从栈顶开始一个一个地弹出,直到取到需要的盘子。

如何在C++中实现栈?

C++中实现栈最常用的方法是使用STL库中的stack。它提供了一系列函数用于实现栈的功能,包括:

  • push():在栈顶插入一个元素
  • pop():弹出并删除栈顶元素
  • top():返回栈顶元素的值
  • empty():检查栈是否为空
  • size():返回栈的大小

stack的定义如下:

#include <stack>

std::stack<int> myStack; // 这行代码定义了一个名为myStack的栈,存储int类型的元素

示例一:使用栈判断括号是否匹配

栈经常用于处理括号匹配问题。我们可以定义一个栈,遇到左括号则将其压入栈顶,遇到右括号则弹出栈顶元素并判断是否与此右括号匹配,若不匹配则括号不匹配。

以括号匹配为例,下面是一个示例程序:

#include <iostream>
#include <stack>

bool isBalanced(std::string str) {
    std::stack<char> myStack; // 定义一个char类型的栈
    for (char c : str) {
        if (c == '{' || c == '[' || c == '(') {
            myStack.push(c); // 左括号压入栈顶
        } else if (c == '}' || c == ']' || c == ')') {
            if (myStack.empty()) {
                return false; // 栈为空时,右括号未匹配
            }
            char top = myStack.top(); // 获取栈顶元素
            myStack.pop(); // 弹出栈顶元素
            if (c == '}' && top != '{') {
                return false; // 不匹配则返回false
            } else if (c == ']' && top != '[') {
                return false;
            } else if (c == ')' && top != '(') {
                return false;
            }
        }
    }
    return myStack.empty(); // 栈为空则括号匹配,否则不匹配
}

int main() {
    std::string str = "{[()]()}"; // 测试字符串
    if (isBalanced(str)) {
        std::cout << "括号匹配" << std::endl;
    } else {
        std::cout << "括号不匹配" << std::endl;
    }
    return 0;
}

在上述代码中,函数isBalanced接收一个字符串作为参数,返回一个布尔值以表示该字符串中的括号是否匹配。函数内部定义了一个char类型的栈myStack,通过遍历字符串str中的每一个字符判断是否为左括号或右括号,并根据左右括号的特性进行匹配判断。最终,如果栈为空,则说明括号匹配,否则不匹配。

示例二:使用栈将中缀表达式转换为后缀表达式

栈还可以用于将中缀表达式转换为后缀表达式。中缀表达式是我们平常使用的表达式形式,例如3 + 4 * 2 / ( 1 - 5 ) ^ 2。而后缀表达式则是将操作数放在前面、操作符放在后面的表达式形式,例如3 4 2 * 1 5 - 2 ^ / +

将中缀表达式转换为后缀表达式需要使用到栈。我们可以依次遍历中缀表达式中的每个元素:

  • 如果是操作数,则直接输出
  • 如果是左括号,则入栈
  • 如果是右括号,则将栈中元素弹出并输出,直到弹出左括号为止
  • 如果是操作符,则判断其优先级与栈顶操作符的优先级,如果更低(或相等)则弹出栈顶元素并输出,直到栈顶操作符的优先级小于该操作符
  • 如果遍历完成后栈中还有元素,则依次弹出并输出直到栈为空

下面是将中缀表达式转换为后缀表达式的示例程序:

#include <iostream>
#include <stack>
#include <string>
#include <sstream>

int priority(char op) {
    if (op == '+' || op == '-') {
        return 1;
    } else if (op == '*' || op == '/') {
        return 2;
    } else if (op == '^') {
        return 3;
    }
    return 0;
}

std::string infixToPostfix(std::string str) {
    std::stringstream ss;
    std::stack<char> myStack;

    for (char c : str) {
        if (isdigit(c)) {
            ss << c; // 如果是数字则直接输出
        } else if (c == '(') {
            myStack.push(c); // 如果是左括号则入栈
        } else if (c == ')') {
            while (!myStack.empty() && myStack.top() != '(') {
                ss << myStack.top(); // 弹出栈顶元素并输出,直到弹出左括号为止
                myStack.pop();
            }
            if (!myStack.empty() && myStack.top() == '(') {
                myStack.pop(); // 弹出左括号
            }
        } else {
            while (!myStack.empty() && priority(c) <= priority(myStack.top())) {
                ss << myStack.top(); // 弹出栈顶元素并输出,直到栈顶操作符的优先级小于该操作符
                myStack.pop();
            }
            myStack.push(c); // 将该操作符入栈
        }
    }

    while (!myStack.empty()) {
        ss << myStack.top(); // 如果栈中还有元素,则依次弹出并输出直到栈为空
        myStack.pop();
    }

    return ss.str(); // 返回后缀表达式
}

int main() {
    std::string str = "3+4*2/(1-5)^2"; // 中缀表达式
    std::string postfix = infixToPostfix(str); // 将中缀表达式转换为后缀表达式
    std::cout << postfix << std::endl; // 输出后缀表达式
    return 0;
}

在上述代码中,函数infixToPostfix接收一个字符串作为参数,返回一个字符串表示后缀表达式。函数内部定义了一个char类型的栈myStack,通过遍历输入字符串中的每一个字符,根据其是操作数、左括号、右括号还是操作符进行不同的操作,并输出后缀表达式。最终,返回后缀表达式字符串。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++中栈结构建立与操作详细解析 - Python技术站

(0)
上一篇 2023年6月20日
下一篇 2023年6月20日

相关文章

  • C++基于递归和非递归算法判定两个二叉树结构是否完全相同(结构和数据都相同)

    下面是 C++ 基于递归和非递归算法判定两个二叉树结构是否完全相同(结构和数据都相同)的详细攻略: 问题分析 题目要求我们判断两个二叉树的结构和数据是否完全相同。这里所说的“结构相同”指的是两棵树的节点数、节点的左右子树结构相同,而“数据相同”指的是两棵树的节点存储的数据值相等。 递归算法实现 递归是二叉树算法中最经典的算法之一,而判断两个二叉树结构是否相同…

    other 2023年6月27日
    00
  • 魔兽世界7.3.5邪DK怎么堆属性 wow7.35邪DK配装属性优先级攻略

    魔兽世界7.3.5邪DK怎么堆属性 配置暗影评估 邪DK的核心伤害技能是暗影打击,因此需要优先配置暗影伤害。通过暗影评估属性可以有效提高暗影打击的伤害,同时也能提高瘟疫打击和心脏打击的伤害,因此建议优先配置暗影评估属性。 暗影评估属性的堆叠可以通过以下几种方式来实现: 增加暗影评估技能的等级,这能够让每次暗影打击的伤害都得到高额提升。 堆叠暗影伤害的装备和宝…

    other 2023年6月27日
    00
  • Win11提示找不到文件请确定文件名是否正确怎么解决?

    Win11提示找不到文件的错误提示可能会出现在系统的各个部分,例如在桌面或文件资源管理器中打开文件夹,打开程序等操作时都有可能出现此类提示。此错误提示通常有以下几个原因: 文件被删除或移动,导致路径不正确,系统无法找到。 文件名中将中文空格、标点符号作为文件名,导致系统无法解析文件名。 文件被病毒或恶意软件感染,导致无法使用。 针对以上错误,我们可以尝试一下…

    other 2023年6月26日
    00
  • 利用DIR命令批量输出文件夹名或文件名的代码

    使用DIR命令可以批量输出指定目录下的文件夹名或文件名。以下是利用DIR命令批量输出文件夹名或文件名的完整攻略: 1. 打开命令行窗口 在Windows系统中,按下“Win+R”快捷键打开运行窗口,输入“cmd”并点击“确定”即可打开命令行窗口。 2. 定位到指定目录 使用CD命令可以切换当前目录,例如“CD D:\test”表示切换到D盘下的test文件夹…

    other 2023年6月26日
    00
  • 如何恢复TP-LINK无线路由器的用户名和密码?

    如何恢复TP-LINK无线路由器的用户名和密码? 如果您忘记了TP-LINK无线路由器的用户名和密码,恢复甚至重置路由器是一个不错的解决办法。下面我们详细介绍如何恢复TP-LINK无线路由器的用户名和密码。 步骤一:连接路由器 将计算机或笔记本电脑通过网线连接到 TP-LINK 无线路由器的 LAN 口上,确保您可以通过网线连接到路由器。然后打开浏览器,在地…

    other 2023年6月27日
    00
  • HP笔记本关机自动重启的解决办法

    HP笔记本关机自动重启的解决办法 如果您的HP笔记本在关机时会自动重启,无法正确地关闭,则需要考虑以下解决办法。 1. 禁用自动重启 在Windows 10设备管理器中,可以禁用系统重启以修复问题: 打开Windows 10设备管理器。 展开“系统设备”下的“电源管理器”。 找到“Microsoft ACPI-兼容系统”此项,并双击打开它。 单击“驱动程序”…

    other 2023年6月27日
    00
  • 创建java多线程程序

    下面是创建Java多线程程序的完整攻略: 1.理解Java多线程概念 在Java中,线程是轻量级的执行单元,它允许程序同时执行多个任务。多线程可以提高程序的效率,因为多个任务可以并行执行,节约了时间。 2.创建Java多线程程序 2.1 方式一:继承Thread类 创建Java多线程程序的一种方式是继承Thread类并实现run()方法。 class MyT…

    other 2023年6月26日
    00
  • C语言中#pragma once的作用

    C语言中#pragma once是用于防止头文件被重复引用的一种预处理指令。下面详细讲解它的作用和使用方法。 一、作用 #pragma once的作用是用于防止C/C++程序中的头文件被重复引用。头文件中常常定义了一些宏、类型和函数等,当一个头文件被多次引用时就会产生重复定义的错误。使用#pragma once能够保证同一头文件只在编译器中被包含一次,从而避…

    other 2023年6月26日
    00
合作推广
合作推广
分享本页
返回顶部