【数据结构】栈

本文更新于个人博客Burnside Blog

总的来说,栈(Stack)是一种应用十分广泛的线性数据结构,我们大多数时候可以把它理解成一个杯子,杯子只有一个口,它既是进入的入口,也是退出的出口。的确如此,栈是一种先入后出(LIFO)的数据结构,它支持插入与删除两种操作,且两个操作仅可以在一端进行。

为了方便起见,我们不使用动态方式生成一个栈,或销毁一个栈,我们只考虑一个静态的栈的功能实现。栈中的元素可以是任何的用户自定义类型,为了方便起见,我们假设元素的类型为int,如需要别的类型,只需要灵活处理即可。接下来我们申请一块长度为MaxSize的连续内存来存储这个栈,这时它又被称为顺序栈。

int Stack[MaxSize];

这样我们就成功获得了一个自己的栈。考虑往栈中插入元素或删除元素,所改变的只有最顶部的元素距栈底的距离,这里的距离表示的是元素个数,我们把这个顶部称为栈顶,可以用一个变量top来维护,最顶部的元素为栈顶元素,不难发现,每一次的删除操作,总是删除的栈顶元素。

因此,我们会得到栈的几个操作:

1、插入元素

int push(int x){

    Stack[++top]=x;

    return top;

}

插入一个元素很简单,只需要将栈顶指向数组内的下一个位置,然后把该位置赋值为要插入的值即可,函数中的变量x即为需要插入的值,top为栈顶,此函数返回值为插入后的栈顶。注意,当栈为空的时候,变量top应当等于-1。

2、删除元素

int pop(){

    return --top;

}

删除一个元素更简单,只需要将栈顶下移一个就可以。注意,原来的栈顶元素不需要做任何的改变,因为只要插入到这个位置,这个位置就会立马被赋值上被插入的新的元素,所以只需要让栈顶下移即可,而并不需要改变栈顶元素的值。此函数返回的是删除后的栈顶。要注意,这里有一个潜在的问题,如果这个时候栈已空,但仍然调用了pop(),可能会使以后的操作访问到非法位置,因此,请务必确保栈是非空的,再使用pop(),为了方便确保栈是否为空,我们引入一个新的函数。

3、查询栈是否为空

bool empty(){

    return top==-1?true:false;

}

很简单,栈为空的标志为top等于-1,直接调用即可。

4、查询栈现在的大小(size)

int size(){

    return top+1;

}

也很简单,栈的大小为top+1。

5、查询栈顶元素

int top(){

    return Stack[top];

}

请注意,请务必在栈非空的情况下使用该命令。

6、删除栈内的所有元素

void clear(){

    while(!empty()) pop();

}

很自然的实现,当栈为非空时,一直删除元素就可以了。

以上为栈的所有操作,部分书中还介绍了链式栈,本文中不再涉及,具体的实现思想与上述六个函数一样。

栈有很多实际的应用,其中常见的有:把一个十进制数拆分为二进制,查询一个括号序列是否能够匹配,计算表达式的值等。我们主要来写查询括号序列是否匹配,剩下两个常见功能读者可以自行完成。

括号序列,是仅由(与)构成的序列,匹配的定义如下:

1. ()是一个合法匹配。

2. 如果A是一个合法匹配,则(A)是一个合法匹配。

3. 如果A和B都是合法匹配,则AB是一个合法匹配。

不难发现,()()(())((())())是一个合法匹配,而(()不是一个合法匹配。

判断的过程也很轻松,我们只需要模拟这个匹配的过程就可以了,具体操作步骤如下:

1. 如果当前读取到一个(,进栈,读取下一位。

2. 如果当前读取到一个),如果栈非空,取栈顶的右括号与之匹配,读取下一位;如果栈空,则找不到括号与之匹配,证明其不合法。

3. 如果读完了整个括号序列栈空,则整个括号序列合法,否则不合法。

正确性显然,不过多赘述,代码如下:

#include<iostream>

#include<cstdio>

const int MaxSize=1000;

char Stack[MaxSize];

int top=-1,flag=true;

int main(){

    char c;

    while((c=getchar())!=EOF){

        if(c=='(') Stack[++top]='(';

        else{

            if(top==-1){

                flag=false;

                break;

            }

            top--;

        }

    }

    if(top!=-1) flag=false;

    printf(flag?"legal":"illegal");

    return 0;

}

可能会有人表示输出总是illegal,因为在一开始读的时候把回车也读进去了,可以使用文件输入输出,最后不换行就可以了,或者可以采用其他的输入方式。

在某些特殊应用中,还会使用到单调栈,因为仅在竞赛中常用,因此不在本文中描述。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一,栈 栈是存放对象的一种特殊容器,在插入与删除对象时,这种结构遵循后进先出(Last-in-first-out,...
    峰峰小阅读 888评论 0 4
  • 基于数据结构(C语言)实现栈的基本操作和数值转换应用 #include #include #include<mal...
    掌灬纹阅读 623评论 0 3
  • 一:概述 由图我们可看成栈只能从栈顶存取元素,同时先进入的元素反而是后出,而栈顶永远指向栈内最顶部的元素。到此可以...
    涂豪_OP阅读 614评论 0 0
  • 1. 栈 Stack 定义:限定仅在表尾进行插入和删除操作的线性表。即后进先出的线性表(Last In First...
    Lost_Robot阅读 1,261评论 0 1
  • 1.栈的介绍 栈的英文为(stack) 栈是一个先入后出(FILO-First In Last Out)的有序列表...
    smallmartial阅读 288评论 0 0