第三章 栈

判断题

在这里插入图片描述

单选题

在这里插入图片描述

程序填空题

在这里插入图片描述

函数题

6-1 在一个数组中实现两个堆栈 (15 分)
本题要求在一个数组中实现两个堆栈。

函数接口定义:
Stack CreateStack( int MaxSize );
bool Push( Stack S, ElementType X, int Tag );
ElementType Pop( Stack S, int Tag );
其中Tag是堆栈编号,取1或2;MaxSize堆栈数组的规模;Stack结构定义如下:

typedef int Position;
struct SNode {
ElementType *Data;
Position Top1, Top2;
int MaxSize;
};
typedef struct SNode *Stack;
注意:如果堆栈已满,Push函数必须输出“Stack Full”并且返回false;如果某堆栈是空的,则Pop函数必须输出“Stack Tag Empty”(其中Tag是该堆栈的编号),并且返回ERROR。

裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>

#define ERROR 1e8
typedef int ElementType;
typedef enum { push, pop, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
struct SNode {
ElementType *Data;
Position Top1, Top2;
int MaxSize;
};
typedef struct SNode *Stack;

Stack CreateStack( int MaxSize );
bool Push( Stack S, ElementType X, int Tag );
ElementType Pop( Stack S, int Tag );

Operation GetOp(); /* details omitted /
void PrintStack( Stack S, int Tag ); /
details omitted */

int main()
{
int N, Tag, X;
Stack S;
int done = 0;

scanf("%d", &N);
S = CreateStack(N);
while ( !done ) {
    switch( GetOp() ) {
    case push: 
        scanf("%d %d", &Tag, &X);
        if (!Push(S, X, Tag)) printf("Stack %d is Full!\n", Tag);
        break;
    case pop:
        scanf("%d", &Tag);
        X = Pop(S, Tag);
        if ( X==ERROR ) printf("Stack %d is Empty!\n", Tag);
        break;
    case end:
        PrintStack(S, 1);
        PrintStack(S, 2);
        done = 1;
        break;
    }
}
return 0;

}

/* 你的代码将被嵌在这里 */
输入样例:
5
Push 1 1
Pop 2
Push 2 11
Push 1 2
Push 2 12
Pop 1
Push 2 13
Push 2 14
Push 1 3
Pop 2
End
输出样例:
Stack 2 Empty
Stack 2 is Empty!
Stack Full
Stack 1 is Full!
Pop from Stack 1: 1
Pop from Stack 2: 13 12 11

代码如下

Stack CreateStack( int MaxSize )
{
    Stack S =(Stack)malloc(sizeof(struct SNode));
    S->Data=(ElementType*)malloc(sizeof(ElementType)*MaxSize);
    S->Top1=-1;
    S->Top2=MaxSize;
    S->MaxSize=MaxSize;
    return S;
}
bool Push( Stack S, ElementType X, int Tag )
{
    if(S->Top2-S->Top1==1){
        printf("Stack Full\n");
        return false;
    }
    if(Tag==1){
        S->Data[++(S->Top1)]=X;
        return true;
    }
    else{
        S->Data[--(S->Top2)]=X;
        return true;
    }
}
ElementType Pop( Stack S, int Tag )
{
      if(Tag==1){
        if(S->Top1==-1){
            printf("Stack %d Empty\n",Tag);
            return ERROR;
        }
        return S->Data[(S->Top1)--];
    }
    else{
        if(S->Top2==S->MaxSize){
            printf("Stack %d Empty\n",Tag);
            return ERROR;
        }
        return S->Data[(S->Top2)++];
    }
}

6-2 另类堆栈 (15 分)
在栈的顺序存储实现中,另有一种方法是将Top定义为栈顶的上一个位置。请编写程序实现这种定义下堆栈的入栈、出栈操作。如何判断堆栈为空或者满?

函数接口定义:
bool Push( Stack S, ElementType X );
ElementType Pop( Stack S );
其中Stack结构定义如下:

typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode {
ElementType Data; / 存储元素的数组 /
Position Top; /
栈顶指针 /
int MaxSize; /
堆栈最大容量 */
};
typedef PtrToSNode Stack;
注意:如果堆栈已满,Push函数必须输出“Stack Full”并且返回false;如果队列是空的,则Pop函数必须输出“Stack Empty”,并且返回ERROR。

裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>

#define ERROR -1
typedef int ElementType;
typedef enum { push, pop, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode {
ElementType Data; / 存储元素的数组 /
Position Top; /
栈顶指针 /
int MaxSize; /
堆栈最大容量 */
};
typedef PtrToSNode Stack;

Stack CreateStack( int MaxSize )
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
S->Top = 0;
S->MaxSize = MaxSize;
return S;
}

bool Push( Stack S, ElementType X );
ElementType Pop( Stack S );

Operation GetOp(); /* 裁判实现,细节不表 /
void PrintStack( Stack S ); /
裁判实现,细节不表 */

int main()
{
ElementType X;
Stack S;
int N, done = 0;

scanf("%d", &N);
S = CreateStack(N);
while ( !done ) {
    switch( GetOp() ) {
    case push: 
        scanf("%d", &X);
        Push(S, X);
        break;
    case pop:
        X = Pop(S);
        if ( X!=ERROR ) printf("%d is out\n", X);
        break;
    case end:
        PrintStack(S);
        done = 1;
        break;
    }
}
return 0;

}

/* 你的代码将被嵌在这里 */
输入样例:
4
Pop
Push 5
Push 4
Push 3
Pop
Pop
Push 2
Push 1
Push 0
Push 10
End
输出样例:
Stack Empty
3 is out
4 is out
Stack Full
0 1 2 5

代码如下

bool Push( Stack S, ElementType X )
{
    if(S->Top == S->MaxSize){
        printf("Stack Full\n");
        return false;
    }
        S->Data[++(S->Top)]=X;
        return true;
}
ElementType Pop( Stack S ){
        if(S->Top==0){
            printf("Stack Empty\n");
            return ERROR;
        }
    return S->Data[(S->Top)--];
}

编程题

7-1 符号配对 (20 分)
请编写程序检查C语言源程序中下列符号是否配对://、(与)、[与]、{与}。

输入格式:
输入为一个C语言源程序。当读到某一行中只有一个句点.和一个回车的时候,标志着输入结束。程序中需要检查配对的符号不超过100个。

输出格式:
首先,如果所有符号配对正确,则在第一行中输出YES,否则输出NO。然后在第二行中指出第一个不配对的符号:如果缺少左符号,则输出?-右符号;如果缺少右符号,则输出左符号-?。

输入样例1:
void test()
{
int i, A[10];
for (i=0; i<10; i++) /*/
A[i] = i;
}
.

输出样例1:
NO
/*-?
输入样例2:
void test()
{
int i, A[10];
for (i=0; i<10; i++) /**/
A[i] = i;
}]
.

输出样例2:
NO
?-]
输入样例3:
void test()
{
int i
double A[10];
for (i=0; i<10; i++) /**/
A[i] = 0.1*i;
}
.

输出样例3:
YES

代码如下

在这里插入代码片

7-2 表达式转换 (25 分)
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。

输入格式:
输入在一行中给出不含空格的中缀表达式,可包含+、-、*、\以及左右括号(),表达式不超过20个字符。

输出格式:
在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。

输入样例:
2+3*(7-4)+8/4
输出样例:
2 3 7 4 - * + 8 4 / +
作者: DS课程组
单位: 浙江大学
时间限制: 400 ms
内存限制: 64 MB

代码如下
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum { push, pop, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode
{
    char *Data;  /* 存储元素的数组 */
    Position Top;       /* 栈顶指针       */
    int MaxSize;        /* 堆栈最大容量   */
};
typedef PtrToSNode Stack;

Stack CreateStack( )
{
    Stack S = (Stack)malloc(sizeof(struct SNode));
    S->Data = (char *)malloc(25 * sizeof(char));
    S->Top = 0;
    S->MaxSize = 25;
    return S;
}
bool IsNum(char c);
bool Ischar(char c);
bool judge( char a, char b);
int main()
{
    Stack S;
    S=CreateStack();
    char ch[25];
    int len;
    int space =0;
    scanf("%s",ch);
    len = strlen(ch);
    for(int i=0; i<len; i++)
    {
        if(IsNum(ch[i]))
        {
            if( space )
            {
                printf(" ");
                space = 0;
            }
            printf("%c",ch[i]);
        }
        else
        {
            if(S->Top)
            {
                if(ch[i]==')')
                {
                    while( S->Top--)
                    {
                        if(S->Data[S->Top]=='('){
                            break;
                        }
                        printf(" %c",S->Data[S->Top]);
                    }
                }
                else
                {
                    while(S->Top )
                    {
                        if( judge( S->Data[S->Top-1],ch[i]))
                        {
                            printf(" %c",S->Data[--S->Top]);
                        }
                        else
                            break;
                    }
                    S->Data[S->Top++] = ch[i];
                }
            }
            else
                S->Data[S->Top++] = ch[i];
                for (int j=0; j< S->Top; j++)
            {
                if( S->Data[j]!='(')
                 {
                     space = 1;
                     break;
                 }
            }
        }
    }
    while (S->Top)
            {
                printf(" %c",S->Data[--S->Top]);
            }
            return 0;
}
bool IsNum( char c)
{
    if(c >='0'&&c<='9')
        return true;
        else
            return false;
}

bool Ischar( char c)
{
    if(c=='+' || c=='-')
        return true;
        else
            return false;
}

bool judge( char a,char b)
{
    if( b==')')
        return true;
    if( b=='(' || a=='(')
        return false;

    switch(b)
    {
    case '+':
    case '-':
        return true;
        break;
    case '*':
    case '/':
        switch(a)
        {
        case '+':
        case '-':
            return false;
            break;
        case '*':
        case '/':
            return true;
            break;
        }

    }
}

7-3 堆栈操作合法性 (20 分)
假设以S和X分别表示入栈和出栈操作。如果根据一个仅由S和X构成的序列,对一个空堆栈进行操作,相应操作均可行(如没有出现删除时栈空)且最后状态也是栈空,则称该序列是合法的堆栈操作序列。请编写程序,输入S和X序列,判断该序列是否合法。

输入格式:
输入第一行给出两个正整数N和M,其中N是待测序列的个数,M(≤50)是堆栈的最大容量。随后N行,每行中给出一个仅由S和X构成的序列。序列保证不为空,且长度不超过100。

输出格式:
对每个序列,在一行中输出YES如果该序列是合法的堆栈操作序列,或NO如果不是。

输入样例:
4 10
SSSXXSXXSX
SSSXXSXXS
SSSSSSSSSSXSSXXXXXXXXXXX
SSSXXSXXX
输出样例:
YES
NO
NO
NO
作者: DS课程组
单位: 浙江大学
时间限制: 400 ms
内存限制: 64 MB
代码长度限制: 16 KB

代码如下

#include<stdio.h>

int main()
{
    int m,n;
    scanf("%d%d ",&m,&n);
    for(int i = 0; i < m; i ++) {
        char s;
        int cont =0;
        int len =0;
        int flag =1;
        while((s = getchar()) != '\n') {
            if(s == 'S') {
                cont++;
                if(cont > n){
                    flag =0;
                    continue;
                }
            }
            if(s == 'X') {
                cont--;
                if(cont < 0){
                    flag =0;
                }
            }
            if(len > n){
                flag = 0;
                continue;
            }
        }
        if (cont==0&&flag == 1)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

7-4 逆波兰表达式求值 (20 分)
逆波兰表示法是一种将运算符(operator)写在操作数(operand)后面的描述程序(算式)的方法。举个例子,我们平常用中缀表示法描述的算式(1 + 2)*(5 + 4),改为逆波兰表示法之后则是1 2 + 5 4 + *。相较于中缀表示法,逆波兰表示法的优势在于不需要括号。
请输出以逆波兰表示法输入的算式的计算结果。

输入格式:
在一行中输入1个算式。相邻的符号(操作数或运算符)用1个空格隔开。

输出格式:
在一行中输出计算结果。

限制:
2≤算式中操作数的总数≤100
1≤算式中运算符的总数≤99
运算符仅包括“+”、“-”、“*”,操作数、计算过程中的值以及最终的计算结果均在int范围内。

输入样例1:
4 3 + 2 -
输出样例1:
5
输入样例2:
1 2 + 3 4 - *
输出样例2:
-3
作者: 李廷元
单位: 中国民用航空飞行学院
时间限制: 400 ms
内存限制: 64 MB

代码如下

在这里插入代码片

7-5 求前缀表达式的值 (25 分)
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。

输入格式:
输入在一行内给出不超过30个字符的前缀表达式,只包含+、-、*、/以及运算数,不同对象(运算数、运算符号)之间以空格分隔。

输出格式:
输出前缀表达式的运算结果,保留小数点后1位,或错误信息ERROR。

输入样例:

    • 2 * 3 - 7 4 / 8 4
      输出样例:
      13.0

代码如下

在这里插入代码片

7-6 列车厢调度 (25 分)
1 ====== <–移动方向
/
3 =====

2 ====== -->移动方向
大家或许在某些数据结构教材上见到过“列车厢调度问题”(当然没见过也不要紧)。今天,我们就来实际操作一下列车厢的调度。对照上方的ASCII字符图,问题描述如下:

有三条平行的列车轨道(1、2、3)以及1-3和2-3两段连接轨道。现有一列车厢停在1号轨道上,请利用两条连接轨道以及3号轨道,将车厢按照要求的顺序转移到2号轨道。规则是:

每次转移1节车厢;
处在1号轨道的车厢要么经过1-3连接道进入3号轨道(该操作记为"1->3"),要么经过两条连接轨道直接进入2号轨道(该操作记为"1->2");
一旦车厢进入2号轨道,就不可以再移出该轨道;
处在3号轨道的车厢,只能经过2-3连接道进入2号轨道(该操作记为"3->2");
显然,任何车厢不能穿过、跨越或绕过其它车厢进行移动。
对于给定的1号停车顺序,如果经过调度能够实现2号轨道要求的顺序,则给出操作序列;如果不能,就反问用户 Are(你) you(是) kidding(凯丁) me(么)?

输入格式:
两行由大写字母组成的非空字符串,第一行表示停在1号轨道上的车厢从左到右的顺序,第二行表示要求车厢停到2号轨道的进道顺序(输入样例1中第二行CBA表示车厢在2号轨道的停放从左到右是ABC,因为C最先进入,所以在最右边)。两行字符串长度相同且不超过26(因为只有26个大写字母),每个字母表示一节车厢。题目保证同一行内的字母不重复且两行的字母集相同。

输出格式:
如果能够成功调度,给出最短的操作序列,每个操作占一行。所谓“最短”,即如果1->2可以完成的调度,就不要通过1->3和3->2来实现。如果不能调度,输出 “Are you kidding me?”

输入样例1:
ABC
CBA
输出样例1:
1->3
1->3
1->2
3->2
3->2
输入样例2:
ABC
CAB
输出样例2:
Are you kidding me?

代码如下

#include<stdio.h>
#include <stdlib.h>
#include<string.h>
typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode {
    char *Data;  /* 存储元素的数组 */
    Position Top;       /* 栈顶指针       */
    int MaxSize;        /* 堆栈最大容量   */
};
typedef PtrToSNode Stack;

Stack CreateStack(  )
{
    Stack S = (Stack)malloc(sizeof(struct SNode));
    S->Data = (char *)malloc(30 * sizeof(char));
    S->Top = 0;
    S->MaxSize = 30;
    return S;
}

int main()
{
    Stack S;
    S= CreateStack();
    char str1[30];
    char str2[30];
    int result[50];
	int flag=1;
	scanf("%s",str1);
	int len=strlen(str1);
	scanf("%s",str2);
	int t1=0,t2=0,k=0;
	while(1)
	{
		if(t1<len&&str1[t1]==str2[t2])
		{
			t1++;
			t2++;
			result[k++]=12;
		}
		else if(S->Top&&S->Data[S->Top-1]==str2[t2])
		{
			S->Top--;
			t2++;
			result[k++]=32;
		}
		else
		{
			if(t2 == len)
			{
				break;
			}
			S->Data[S->Top++]=str1[t1++];
			result[k++]=13;
			if(t1>=len)
			{
				flag=0;
				break;
			}
		}
	}
	if(flag==0||S->Top)
        printf("Are you kidding me?\n");
	else{
		for(int i=0;i<k;i++)
		{
			if(result[i]==12)
			  printf("1->2\n");
			else if(result[i]==13)
			  printf("1->3\n");
			else if(result[i]==32)
			  printf("3->2\n");
		}
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第3章是数据结构中非常重要的一章,属于线性表的一种特殊形式,具有先进后出的特点。在这章节中,我们介绍了的基本概念、顺序的实现以及链的实现。以下是对顺序和链结构ADTList的基本操作的实现与测试的回答。 顺序的基本操作的实现如下: 1. 初始化:定义一个固定大小的数组,用来存储的元素,同时将顶指针置为-1. 2. 入操作:将元素插入到顶位置,然后将顶指针加1. 3. 出操作:将顶元素弹出,然后将顶指针减1. 4. 判断空:如果顶指针等于-1,则说明为空. 5. 判断满:如果顶指针等于数组大小减1,则说明已满. 6. 获取顶元素:返回顶元素的值,但不改变的状态. 以下是对顺序的测试: 1. 创建一个顺序对象. 2. 入若干元素,比如依次入1, 2, 3. 3. 判断空,应该返回false. 4. 获取顶元素,应该返回3. 5. 出一个元素,然后判断顶元素,应该返回2. 6. 重复步骤5若干次,直到为空. 7. 判断空,应该返回true. 链的基本操作的实现如下: 1. 初始化:创建一个空链表,顶指针指向链表头节点. 2. 入操作:创建一个新节点,将元素值赋给新节点,并将新节点插入到链表头部. 3. 出操作:删除链表头节点,并将顶指针指向新的链表头节点. 4. 判断空:如果顶指针为空,则说明为空. 5. 获取顶元素:返回顶节点的元素值,但不改变的状态. 以下是对链的测试: 1. 创建一个链对象. 2. 入若干元素,比如依次入1, 2, 3. 3. 判断空,应该返回false. 4. 获取顶元素,应该返回3. 5. 出一个元素,然后判断顶元素,应该返回2. 6. 重复步骤5若干次,直到为空. 7. 判断空,应该返回true. 以上就是对的顺序和链结构ADTList基本操作的实现与测试的回答。在实现时,可以使用编程语言来进行具体的实现,并运行相应的测试代码来验证实现的正确性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值