判断题
单选题
程序填空题
函数题
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
- 2 * 3 - 7 4 / 8 4
代码如下
在这里插入代码片
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;
}