九度题目1108——堆栈的使用

来源:互联网 发布:网络舆情监控软件 编辑:程序博客网 时间:2024/06/05 18:58
堆栈的使用

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:4344

解决:1249

题目描述:

    堆栈是一种基本的数据结构。堆栈具有两种基本操作方式,push 和 pop。Push一个值会将其压入栈顶,而 pop 则会将栈顶的值弹出。现在我们就来验证一下堆栈的使用。

输入:

     对于每组测试数据,第一行是一个正整数 n,0<n<=10000(n=0 结束)。而后的 n 行,每行的第一个字符可能是'P’或者'O’或者'A’;如果是'P’,后面还会跟着一个整数,表示把这个数据压入堆栈;如果是'O’,表示将栈顶的值 pop 出来,如果堆栈中没有元素时,忽略本次操作;如果是'A’,表示询问当前栈顶的值,如果当时栈为空,则输出'E'。堆栈开始为空。

输出:

    对于每组测试数据,根据其中的命令字符来处理堆栈;并对所有的'A’操作,输出当时栈顶的值,每个占据一行,如果当时栈为空,则输出'E’。当每组测试数据完成后,输出一个空行。

样例输入:
3AP 5A4P 3P 6O A0
样例输出:
E53
对题目的理解:
1、关于“堆栈”的理解,首先我们会想“堆栈”和“堆”、“栈”是什么关系?这个问题会越想越复杂的啦,网上有些资料说“堆栈”简称“栈”,但在这个题目里呢,就不必纠结它到底是个什么东西,有什么特征,题目里面已经给出了它的定义和特征,这是题目里的定义和特征,做这个题目也只需要题目里的定义和特征,定义是一种数据结构,特征就是Pop和Push。
2、知道了题目中”堆栈“的特征就需要来实现了,是使用数组还是连接,栈在大小明确的情况下使用的是数组。我们使用数组。定义数组大小MAXSIZE = 10001。
在C++中的stack是deque(双端队列)的适配器,使用的是分段数组的实现方式。
vector使用的数组实现方式,它的自增功能采用数组空间用完,然后分配一个更大的空间,把之前的数组拷贝进去,释放之前的数组空间。可以探究一下为什么要使用数组实现方式?实验室一位牛掰师兄给出了他的看法,deque是头尾删除,vector需要随机访问,数组结构随机访问时间复杂度为0(1)。

C++版本:
#include <stdio.h>#include <iostream>#define MAXSIZE 10001using namespace std;int stack[MAXSIZE];int push(int i){        int value;        cin>>value;        stack[++i] = value;        return i;}void getop(int i){        if(i < 0)                printf("E\n");        else                printf("%d\n",stack[i]);}int pop(int i){        if(i >= 0)                i--;        return i;}int main(void){int n;int top;char d; while(cin >> n && n != EOF ){ top = -1; int i;  for(i = 1; i <= n; ++i){  char c;  cin>>c;  switch(c){case 'A':getop(top);break;case 'P':top = push(top);break;case 'O':top = pop(top);break;   }}        printf("\n");    }return 0;}

C版本:
#include <stdio.h>#define MAXSIZE 10001int stack[MAXSIZE];int top;void push(){        int value;getchar();        scanf("%d",&value);        stack[++top] = value;}void gettop(){        if(top < 0)                printf("E\n");        else                printf("%d\n",stack[top]);}void pop(){        if(top >= 0)                top--;}int main(){ int n;     while(scanf("%d",&n) != EOF && n !=0 ){ getchar(); top = -1;  for(int i = 1; i <= n; ++i){  char c;  scanf("%c",&c);    switch(c){case 'A':gettop();break;case 'P':push();break;case 'O':pop();   }  while(getchar()!='\n');//为什么这样使用,是因为案例中有一行字母后面<span style="white-space:pre"></span>//不是<span style="font-family: 'MicroSoft Yahei', Helvetica, Arial, Georgia, Simsun; ">直接的换行符,还有一个空格符,</span>
}        printf("\n");    }    return 0;}
C版本的代码在VS2012里面编译会出现编译错误,使用gcc编译器编译在c89下面会出问题,在c99问题里面是完全OK,出现这种问题的原因是c89不允许在for循环里定义变量,必须放在方面,置于VS2012出问题的原因更奇怪,把定义放for语句前面也会报错,据一位牛掰师兄说,可能是因为VS的编译器要求函数里的变量都需要在函数内部的最前面定义(我试了一下这个不太准,其事for循环体内部也是可以定义变量的),但是如果把for语句内部的变量定义语句放到函数的开头处,编译将顺利通过。

题外知识——栈
1、栈是什么?后进先出的数据结构。
与同学讨论遇到诸多问题:
1、scanf和cin输入字符的表现,只能输入可见字符,cin为什么遇到空格会停止输入,cin是如何从输入缓冲区里提取输入的字符,并可以判定是不是自己所需输入字符,并且得到自己的输入结果赋给变量?
2、变量不初始化变量就使用在VS里运行会报错,但是在gcc里运行时不会报错,VS到底是什么原因导致了运行时的错误,在两种环境下都是可以获取变量的地址的,就代表变量在定义时就已经分配了空间。
3、case里面是不能初始化一个变量,但是能够定义一个变量,为什么会出现这个差异?
0 0