栈数据结构详解——从基本操作到常见应用

栈是一种基本的数据结构,具有后进先出(LIFO)的特点。在栈中,最后进入的元素最先被访问。在实际生活中,例如乘坐电梯或使用药片盒时,都可以用栈的概念来解释。在C++中,我们可以使用<stack>头文件提供的栈类实现栈数据结构。

栈的操作

  1. 栈的定义,Stack类同样是模板类,因此需要在尖括内声明数据类型,例如int、float、char等基本数据类型或自定义类型:
stack<Type> S;

定义了一个栈对象S,它存储的元素类型由Type表示。

  1. 将元素item压入栈顶:
S.push(item);

将一个元素item添加到栈的顶部。这相当于将元素放在栈的顶部,而原来在栈顶的元素会被往下推。这就是入栈操作。

  1. 返回栈顶元素,但是不删除该元素:
S.top();

会返回栈顶的元素,但并不从栈中移除它。它用于查看栈中当前位于栈顶的元素,不影响栈原本的结构。

  1. 删除栈顶元素,不返回该元素:
S.pop();

将栈顶的元素从栈中移除,但并不返回该元素的值。因此通常会先使用S.top()获取栈顶元素的值,然后使用S.pop()将其从栈中删除。进行出栈操作,防止出栈元素丢失。

  1. 返回栈中元素个数:
S.size();

返回栈中元素的数量,即栈当前的大小。

  1. 检查栈是否为空:
S.empty();

检查栈是否为空。如果栈中没有任何元素,就认为栈为空,返回true;否则,返回false。你可以使用这个函数来判断是否需要进一步处理栈中的元素。

堆栈数据结构的视频演示

下面是一个我使用Manim(Python库)制作的有关堆栈数据结构后入先出的演示过程。

【Manim】堆栈可视化演示【数据结构】

示例解析:hdu 1062 “Text Reverse”

  • 题目来源:hdu 1062 Text Reverse Hangzhou Dianzi University ACM Team

  • 题目

    • Problem Description
      Ignatius likes to write words in reverse way. Given a single line of text which is written by Ignatius, you should reverse all the words and then output them.
    • Input
      The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
      Each test case contains a single line with several words. There will be at most 1000 characters in a line.
    • Output
      For each test case, you should output the text which is processed.
    • Sample Input
    3
    olleh !dlrow
    m'I morf .udh
    I ekil .mca
    
    • Sample Output
    hello world!
    I'm from hdu.
    I like acm.
    
    • Hint
      Remember to use getchar() to read ‘\n’ after the interger T, then you may use gets() to read a line and process it.
  • 题目(翻译)

    • 题目描述:
      伊格纳修斯喜欢以相反的方式书写单词。给定由伊格纳修斯编写的一行文本,你应该颠倒所有单词的顺序,然后输出它们。
    • 输入:
      输入包含多个测试用例。第一行是一个整数T,表示测试用例的数量。接下来是T行,每行包含若干个单词。每行的长度不超过1000个字符。
    • 输出:
      对于每个测试用例,你应该输出处理后的文本。
    • 示例输入:
    3
    olleh !dlrow
    m'I morf .udh
    I ekil .mca
    
    • 示例输出:
    hello world!
    I'm from hdu.
    I like acm.
    
    • 提示:
      记得使用getchar()来读取整数T后的换行符\n,然后可以使用gets()读取一行并进行处理。
  • 解题思路:

    • 首先我们先声明部分变量。
      int n;//记录输入的测试用例数量
      char ch;//存储读入的字符
      
    • 然后读入数据并且对数据处理。
      scanf("%d", &n);//读取一个整数n
      getchar();//处理输入缓冲区中的换行符
      
    • 设置外层循环,执行n次。
      while (n--);
      
    • 题目要求翻转字符串。我们可以使用栈来模拟该过程。
    • 循环部分。
      • 在内层循环中,定义一个 stack<char> S;,用于存储字符。
      • 使用 ch = getchar(); 从输入中读取一个字符,赋值给变量 ch
      • 进入一个判断语句 if (ch == ' ' || ch == '\n' || ch == EOF),判断读入的字符是否为空格、换行或文件结尾。
      • 如果是空格、换行或文件结尾,进入一个循环 while (!S.empty()),将栈中的元素输出并清除。
      • 使用 printf("%c", S.top()); 输出栈顶元素。
      • 使用 S.pop(); 将栈顶元素弹出,达到清除栈顶的目的。
    • 判断语句。
      • 如果判断到换行符或文件结尾,跳出内层循环。
      • 如果是空格,则输出一个空格。
      • 如果不是空格,则将字符入栈 S.push(ch);
    • 内层循环结束后,输出一个换行符。
    • 外层循环结束后,返回 0,表示程序正常运行结束。
  • 总代码:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    char ch;
    scanf("%d", &n);
    getchar();

    while (n--) {
        stack<char> S;
        while (true) {
            ch = getchar();
            if (ch == ' ' || ch == '\n' || ch == EOF) {
                while (!S.empty()) {
                    printf("%c", S.top());
                    S.pop();
                }
                if (ch == '\n' || ch == EOF)
                    break;
                printf(" ");
            } else {
                S.push(ch);
            }
        }
        printf("\n");
    }
    return 0;
}

上述程序通过栈来翻转字符串。根据题目要求,我们按照空格、换行符或文件结尾作为分隔符,将输入的字符串进行翻转输出。

3. 栈的爆栈问题

栈在使用过程中需要一定的空间来存储元素。如果栈的深度过大或存入栈的数组过大,总数会超过系统为栈分配的空间,导致栈溢出的问题。解决此问题的方法有两种:

  1. 调整系统栈大小:通过在程序中调大系统的栈大小,但这种方法依赖于系统和编译器。
  2. 手工实现栈:可以手动编写栈的数据结构,详细内容可参考本书第10.5节。

本文对栈的使用进行初步介绍。在实际应用中,应根据需求选择合适的数据结构和操作,以实现更高效和准确的算法。

参考资料:

算法竞赛入门到进阶 罗勇军
Problem - 1062 Hangzhou Dianzi University Online Judge 3.0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌云陌丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值