栈是限定仅在表尾进行插入和删除操作的线性表。
我们把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。栈又称为后进先出的线性表,简称LIFO结构。
栈的插入操作,叫作进栈,也称压栈、入栈。
栈的删除操作,叫作出栈,也有的叫作弹栈。
栈的抽象数据类型
ADT 栈(stack) Data 同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系。 Operation InitStack(*S): 初始化操作,建立一个空栈S。 DestroyStack(*S): 若栈存在,则销毁它。 ClearStack(*S): 将栈清空。 StackEmpty(S): 若栈为空,返回True,否则返回False。 GetTop(S,*e): 若栈存在且非空,用e返回S的栈顶元素。 Push(*S,e): 若栈S存在,插入新元素e到栈S中并成为栈顶元素。 Pop(*S,*e): 删除栈S中栈顶元素,并用e返回其值。 StackLength(S): 返回栈S的元素个数。 endADT
栈的顺序存储结构:以首元素作为栈底。两栈共享空间可以提高空间利用率。
栈的链式存储结构:把栈顶放在单链表的头部,用栈顶作为头结点。
如果栈的使用过程中元素变化不可预料,有时很小,有时非常大,那么最好是用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一点。
栈的应用——递归
我们把一个直接调用自己或通过一些列的调用语句间接地调用自己的函数,称为递归函数。
每个递归函数定义必须至少有一个条件,满足时递归不再进行,即不再引用自身而是返回值输出。(避免无穷递归)
例子:斐波拉契数列。
栈的应用——四则运算表达式求值
1)将中缀表达式转化为后缀表达式(栈用来进出运算的符号);
规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级不高于栈顶符号则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
2)将后缀表达式进行运算得出结果(栈用来进出运算的数字)。
规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。