【数据结构入门精讲 | 第五篇】栈知识点及考研408、企业面试练习

本文详细介绍了栈的基础概念,包括顺序栈和链栈的实现原理与异同点,并提供了丰富的判断题、选择题和编程题,帮助读者深入理解栈的性质和应用,适用于考研复习和面试准备。
摘要由CSDN通过智能技术生成

在上一篇中我们进行了表的专项练习,在这篇文章中我们将介绍栈的相关知识点。

在这里插入图片描述

基础概念

栈是限定仅在栈顶(即表首)进行插入和删除操作的线性表,也称为后进先出(Last In First Out) 的线性表,简称 LIFO 结构。

栈的内部实现原理其实就是数组或链表的操作,而之所以引入 栈 这个概念,是为了将程序设计问题模型化,利用栈的先进后出特性对特定的一些问题进行简化。(栈是线性表的特例)

允许插入和删除元素的一端称为栈顶,另一端称为栈底,不含任何任何数据元素的栈称为空栈。

在这里插入图片描述

顺序栈

当使用线性表的顺序存储结构(即数组)实现栈时,该栈被称为顺序栈

伪代码

//创建一个容量为size的空栈
Stack StackInit(int size)
{
    Stack S=malloc(sizeof *S);
S->data=malloc(size *sizeof(StackItem));
S->maxtop=size-1;
S->top=-1;
return S;
}



//判断栈空StackEmpty(S)
int StackEmpty (Stack S) 
{
   return S->top<0;}//top=-1时为空栈



// 判断栈满StackFull(S)
int StackFull (Stack S) 
{
   return S->top==S->maxtop;}//top==maxtop时为满栈



//释放空间StackFree(S)
int StackFree (Stack S) {
   free(S->data); free(S);}



//返回栈顶元素StackItem StackTop(Stack S)
{
    if (StackEmpty(S)) Error("Stack is empty");
else
return S->data[S->top]; //直接返回栈顶top元素即可
}



//入栈操作push(x,S)
void Push (StackItem x, Stack S)
{
    if (StackFull(S)) Error("Stack is full");
else S->data[++S->top]=x;}//前置自加
//x为新的栈顶元素,存放在插⼊前的top+1单元



//出栈操作Pop(S)
void Pop (Stack S)
{
    if (StackEmpty(S)) Error("Stack is empty ");
else return S->data[S->top--];}//后置自减
//删除栈顶元素x后,新的栈顶位置为删除前的top-1单元

注意点:当使用数组存储栈的时候,设数组大小为M,当栈为空时,栈顶指针值为-1,当栈满时,栈顶指针为M-1。若此时入栈,则上溢(overflow)

链栈

当使用线性表的链式存储结构(单链表)实现栈时,该栈被称为链栈。为维护堆栈的FILO的存储特性,链栈中维护的top指针始终指向栈顶元素。

伪代码

//空栈的创建
Stack StackInit()
{
    Stack S=malloc(sizeof *S);
S->top=0;//将top置为空指针,创建一个空栈
return S;
}//o(1)

//检查是否空栈StackEmpty(S)
int StackEmpty (Stack S)
{
   //检测top是否为空指针
return S->top==0;
}

//返回栈顶元素
StackItem StackTop(Stack S)
{
   
if (StackEmpty(S))
Error("Stack is empty");
else return S->top->element;
}

//插入元素
void Push(StackItem x, Stack S)
{
    slink p;
if (StackFull(S)) Error("Stack is Full");
p=NewStackNode();//为元素x创建一个新结点
p->element=x;
p->next=S->top;//修改栈顶结点指针top
S->top=p;//新结点成为新的栈顶指针top
}

//删除元素
StackItem Pop(Stack S)
{
    slink p; StackItem x;
if (StackEmpty(S)) Error("Stack is empty");
x=S->top->element;//将栈顶指针top所指元素放入x中
p=S->top;
S->top=p->next;//修改栈顶指针使其指向栈顶元素的下一个结点
free(p);
return x;
}

顺序栈与链栈的异同点:顺序栈和链栈的时间复杂度均为O(1)
为了使每个栈在算法运行过程中不会溢出,通常要为每个栈预置一个较大的栈空间,但它的优势是存取时定位很方便。

链栈要求每个元素都要配套一个指向下个结点的指针域,增大了内存开销,但好处是栈的长度无限,因此,如果栈的使用过程中元素变化不可预料,有时很小,有时很大,那么最好使用链栈。反之,如果它的变化在可控范围内,则建议使用顺序栈。

接下来让我们进行栈的相关练习。

判断题

1.若一个栈的输入序列为1,2,3,…,N,输出序列的第一个元素是i,则第j个输出元素是j−i−1。(错)

解析:不确定,如果输出的第一个是1,则第二个可以是任何数。

2.栈结构不会出现溢出现象。(错)

链式存储的栈结构不会溢出,但顺序存储的栈结构会溢出,因为它一开始就定义了栈的长度。

3.若一个栈的输入序列为{1, 2, 3, 4, 5},则不可能得到{3, 4, 1, 2, 5}这样的出栈序列。(对)

结合题目且1比2先入栈,所以出栈的顺序肯定是2在1前面,所以不可能得到{3, 4, 1, 2, 5}

4.两个栈共享一片连续空间,可以将两个栈的栈底分别设在这片空间的两端。(对)

选择题

1.若采用带头、尾指针的单向链表表示一个堆栈,那么该堆栈的栈顶指针top应该如何设置?
A.随便哪端作为top都可以
B.链表头、尾都不适合作为top
C.将链表头设为top
D.将链表尾设为top
选C,解析:栈顶为表首,即链表头。

2.给定有限符号集 S , in 和 out 均为 S 中所有元素的任意排列。 对于初始为空的栈 ST, 下列叙述中,正确的是:(选A)
A.若 in 是 ST 的入栈序列,out 是对应 in 的出栈序列, 则 in 与 out 可能互为倒序
B.若 out 是 ST 的出栈序列,则不能判断 in 是否为其可能的入栈序列
C.若 in 是 ST 的入栈序列,out 是对应 in 的出栈序列, 则 in 与 out 一定不同
D.若 in 是 ST 的入栈序列, 则不能判断 out 是否为其可能的出栈序列

3.将5个字母ooops按此顺序入栈,则有多少种不同的出栈顺序可以仍然得到ooops?(选A)
A.5
B.3
C.1
D.6

解析:

  1. o1进o1出、o2进o2出、o3进o3出
  2. o1进o2进、o2出o1出、o3进o3出
  3. o1进o2进、o2出o3进、o3出o1出
  4. o1、o2、o3进,o3、o2、o1出
  5. o1进o1出、o2进o3进、o3出o2出
4.下列关于栈的叙述中,错误的是:

1. 采用非递归方式重写递归程序时必须使用栈
2. 函数调用时,系统要用栈保存必要的信息
3. 只要确定了入栈次序,即可确定出栈次序
4. 栈是一种受限的线性表,允许在其两端进行操作

解析:计算斐波拉契数列迭代实现只需要一个循环即可实现,故12对。3错,不做过多解释。4错,栈是一种受限的线性表,只允许在一端进行操作。

5.若一个栈的入栈序列为1、2、3、…、N,其输出序列为p1、p2、p3、…、pN。若p1=N,则pi为:()
解析:栈的特点是后进先出,入栈序列是 1,2,3,…,n,输出对应的应该是 n,n-1,n-2,…,1,所以答案是 n - i + 1。

6.给定一个堆栈的入栈序列为{ 1, 2, ⋯, n },出栈序列为{ p1, p2, ⋯, pn }。如果p2=n,则存在多少种不同的出栈序列?
解析:在n出栈之前,前n-1个元素都可以第一个出栈,所以答案为n-1。

7.若元素a、b、c、d、e、f依次进栈,允许进栈、退栈操作交替进行,但不允许连续三次进行退栈工作,则不可能得到的出栈序列是?(D)
A.c b d a e f
B.b c a e f d
C.d c e b f a
D.a f e d c b
解析: 假设选项成立,推得其操作即可。

8.在作进栈运算时,应先判别栈是否(① );在作退栈运算时应先判别栈是否(② )。当栈中元素为n个,作进栈运算时发生上溢,则说明该栈的最大容量为(③ )。
①: A. 空 B. 满 C. 上溢 D. 下溢
②: A. 空 B. 满 C. 上溢 D. 下溢
③: A. n-1 B. n C. n+1 D. n/2
A. ① B ② A ③ A
B. ① C ② D ③ B
C. ① B ② A ③ B
D. ① B ② B ③ A
答案选C,解析:在作进栈运算时,应先判别栈是否满。在作退栈运算时应先判别栈是否空。当栈中元素为n个,作进栈运算时发生上溢,则说明该栈的最大容量为n。

9.若一个栈的入栈序列为1、2、3、…、N,输出序列的第一个元素是i,则第j个输出元素是:
A.不确定
B.i−j
C.i−j−1
D.j−i−1
选A,解析:i如果是1,则第j个输出的元素可以是2~N任何一个。

10.设一个堆栈的入栈顺序是1、2、3、4、5。若第一个出栈的元素是4,则最后一个出栈的元素必定是:
A.3
B.1或者5
C.5
D.1
选B,解析:第一个出栈的元素是4,说明这时候5还没入栈,所以下一步可能是入栈或者出栈。

11.检查表达式中的括号是否匹配的问题需要借助________来解决。
A.有向无环图
B.队列
C.二叉搜索树
D.堆栈
选D,解析:具体解析可看后面的编程题。

12.若借助堆栈将中缀表达式a+b*c+(d*e+f)*g转换为后缀表达式,当读入f时,堆栈里的内容是什么(按堆栈自底向上顺序)?
A.+(*+
B.abcde
C.++(+
D.+(+

  • 当输入的是操作数时,直接输出a;

  • 遇到操作符,如果栈为空入栈,+入栈

  • 当输入的是操作数时,直接输出b;

  • 栈顶元素+的优先级小于*的优先级,* 压栈;

  • 当输入的是操作数时,直接输出c;

  • 当输入的是运算符,栈顶元素*的优先级大于+的优先级,* 出栈;循环,栈顶元素+的优先级等于+的优先级,+ 出栈,+入栈;

  • 当输入的是开括号时,把它压栈;

  • 当输入的是操作数时,直接输出d;

  • 当输入的是运算符,因为栈顶是开括号,* 压栈;

  • 当输入的是操作数时,直接输出e;

  • 当输入的是运算符,栈顶元素*的优先级大于+的优先级,* 出栈;+入栈;

当输入的是f停止,此时栈中+(+

总而言之

如果在外面的符号比栈顶符号优先级要高,则入栈
如果外面的小于等于栈顶的,则栈顶出栈;接着再把这个外面的和第二个栈元素比较

13.设有一顺序栈S,元素s1,s2,s3,s4,s5,s6依次进栈,如果6个元素出栈的顺序是s2,s3,s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

秋说

感谢打赏,祝你平安喜乐。

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

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

打赏作者

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

抵扣说明:

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

余额充值