第2章-栈
1. 栈的顺序实现【简单】
请用顺序存储实现栈的数据结构Stack。你所实现的栈应包括:pop,push,top,size,clear,full等功能。利用你实现的Stack实现输入数字的逆序输出。
【输入】整数序列以-1结束,序列长度小于100
【输出】输入整数序列的逆序序列
例如:
【输入】3 9 8 2 5 -1
【输出】5 2 8 9 3
(没错,这个时候我又被C++吓回去了T_T)
#include <stdio.h>
struct stack
{
int data[105];
int top;//top是栈顶下标
} ;
typedef struct stack mstack;
void initialize(mstack *s)
{
s->top = -1;
}
int empty(mstack *s)
{
if(s->top == -1)
return 1;
return 0;
}
int full(mstack *s)
{
if(s->top == 105)
return 1;
return 0;
}
int size(mstack *s)
{
return s->top;
}
void push(mstack *s, int x)
{
if(full(s) == 0){
s->top++;
s->data[s->top] = x;
}
}
void pop(mstack *s)
{
if(empty(s) == 0)
s->top--;
}
int top(mstack *s)
{
if(empty(s) == 0)
return s->data[s->top];
return -1;
}
int main()
{
mstack p;
mstack *s = &p;
initialize(s);
int a;
scanf("%d",&a);
while(a != -1){
push(s,a);
scanf("%d",&a);
}
while(size(s) > -1)
{
printf("%d ",top(s));
pop(s);
}
return 0;
}
2. 10以内的后序波兰式求解【中等】
(10以内的后序波兰式求解) 请编写程序求解10以内的后序波兰式的值。
【输入】合法的10以内的后序波兰式
【输出】后序波兰式的值(按照整型计算的结果)
例如:
【输入】23+6*
【输出】30
【输入】23+* //非法的后序表达式
【输出】none //表示无对应结果
#include <stdio.h>
#include <string.h>
#define max 100
struct stack
{
int data[max];
int top;
} ;
typedef struct stack mstack;
void initialize(mstack *s);
int empty(mstack *s);
int full(mstack *s);
int size(mstack *s);
void push(mstack *s, int x);
void pop(mstack *s);
int top(mstack *s);
int caculate(int a,int b,char ioperator);
int main()
{
mstack p;
mstack *s = &p;
initialize(s);
char a[81];
scanf("%s",a);
int num1,num2,flag=1;
for(int i=0; i<strlen(a); i++){
if(a[i]>='0' && a[i]<='9'){
push(s,a[i]-'0');
continue;
}
if(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/'){
if(size(s) < 1){
printf("none");//栈中少于两个数不合法
flag=0;
break;
}
num1 = top(s);
pop(s);
num2 = top(s);
pop(s);
int temp = caculate(num2,num1,a[i]);
push(s,temp);
}
}
if(size(s)>0){
printf("none");
flag=0;//全部运算完后栈中还有数不合法
}
if(flag)
printf("%d",top(s));
return 0;
}
void initialize(mstack *s)
{
s->top = -1;
}
int empty(mstack *s)
{
if(s->top == -1)
return 1;
return 0;
}
int full(mstack *s)
{
if(s->top == 100)
return 1;
return 0;
}
int size(mstack *s)
{
return s->top;
}
void push(mstack *s, int x)
{
if(full(s) == 0){
s->top++;
s->data[s->top] = x;
}
}
void pop(mstack *s)
{
if(empty(s) == 0)
s->top--;
}
int top(mstack *s)
{
if(empty(s) == 0)
return s->data[s->top];
return -1;
}
int caculate(int a,int b,char ioperator)
{
int c;
switch(ioperator)
{
case '+': c = a+b; break;
case '-': c = a-b; break;
case '*': c = a*b; break;
default: c = a/b; break;
}
return c;
}
3. 出入栈序列判断【中等】
假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,可以操作的序列称为称为合法序列,否则称为非法序列。
例如:
A.IOIIOIOO 合法 B.IOOIOIIO 不合法
C.IIIOIOIO 合法 D.IIIOOIOO 合法
请写出一个算法,判断所给的操作序列是否合法。若合法,返回true,否则返回false
【输入】n n条I和O组成的序列(序列长度<=80)
【输出】n条序列的判断结果(true或者false)
例如:
【输入】
3
IOIIOIOO
IOOIOIIO
IIIOIOIO
【输出】
true
false
true
#include <stdio.h>
#include <string.h>
int judge(char a[])
{
int i,j,cntI,cntO;
for(i=0; i<strlen(a); i++){
cntI=0;
cntO=0;
for(j=0; j<=i; j++){
if(a[j] == 'I'){
cntI++;
}
else{
cntO++;
}
}
if(cntI < cntO)
return 0;
}
return 1;
}
int main()
{
int n,cnt=0;
scanf("%d ",&n);
char a[81];
for(int i=0; i<n; i++){
scanf("%s",a);
(judge(a)==0)? printf("false\n"):printf("true\n");
cnt = 0;
}
return 0;
}
4. 程序代码中的括号匹配【中等】
(程序代码中的括号匹配)请编写程序对一段程序代码中的括号匹配情况进行判断。括号类型有(),[],{}三类,程序代码中可能包含注释,如多行注释/**/和单行注释//,且注释内容不参与括号匹配情况的分析。
【输入】 若干行程序代码,代码长度小于1500个字符
【输出】 除去注释后的括号数量 括号是否匹配(yes/no)
例如:
【输入】
int Collatz(unsigned int n) {
if(n==1) return 0;
else if(n%2) return Collatz(n*3+1)+1;
else return Collatz(n/2)+1;
}
【输出】12 yes
【输入】
float CalcPay( /* [in] */ float payRate, // Employee’s pay rate
/ *[in] */ float hours // Hours worked
){ //return Wages earned()
【输出】 3 no
【输入】"//" ()
【输出】2 yes
#include <iostream>
#include <stdio.h>
#include <string.h>
#define max 100
using namespace std;
void dele(char a[]);
class mystack
{
public:
mystack();
bool Empty()const;
void push(char item);
void pop();
void top(char &item)const;
private:
int cnt;//cnt元素个数
int entry[max];
};
int main()
{
mystack openings;
char str[1501];
//输入
int i=0;
char temp = getchar();
while(temp != EOF){
str[i++] = temp;
temp = getchar();
}
//去除注释
dele(str);
//匹配括号
bool is_matched = true;
int sum = 0;//括号数
char symbol;
for(i=0; i<strlen(str); i++){
symbol = str[i];
if(symbol=='{' || symbol=='[' || symbol=='('){
openings.push(symbol);
sum++;
}
if(symbol=='}' || symbol==']' || symbol==')'){
sum++;
//第一种情况:右括号多于左括号
if(openings.Empty()){
is_matched = false;
}
//第二种情况:进行配对
else{
char match;
char &ch = match;
openings.top(ch);//取左括号进行配对
openings.pop();
is_matched = (symbol=='}'&&match=='{')
||(symbol==']'&&match=='[')
||(symbol==')'&&match=='(');
if(!is_matched)
is_matched = false;
}
}
}
//第三种情况:右括号多于左括号(遍历后栈中还有剩余)
if(!openings.Empty())
is_matched = false;
if(is_matched) cout << sum << ' ' << "yes";
else cout << sum << ' ' << "no";
return 0;
}
mystack::mystack(){
cnt = 0;
}
bool mystack::Empty()const
{
bool outcome = true;
if(cnt>0) outcome = false;
return outcome;
}
void mystack::push(char item)
{
if(cnt < max) entry[cnt++] = item;
}
void mystack::pop()
{
if(cnt > 0) cnt--;
}
void mystack::top(char &item)const
{
if(cnt > 0) item = entry[cnt-1];
}
void dele(char a[])
{
int i;
char *p1,*p2,*temp1,*temp2;
for(i=0; i<strlen(a); i++){
p1 = &a[i];
p2 = &a[i+1];
/*if(*p1=='"' && *p2=='/'){
while(1){
if(a[++i] == '\n')
break;
}
continue;
}*/
if(*p1 == '/'){
if(*p2 == '/'){
temp1 = p1;//记录注释的初始位置
temp2 = p1+2;//进入注释
while(1){
if(*temp2 == '\n')
break;
else temp2++;
}
memset(temp1,1,(temp2-temp1+1)*sizeof(char));
//或把地址从temp1加到temp2挨个清零
}
else if(*p2 == '*'){
temp1 = p1;//记录注释的初始位置
temp2 = p1+2;//进入注释
while(1){
if(*temp2 == '*'){
if(*(temp2 + 1) == '/'){
temp2++;
break;
}
else temp2++;
}
else temp2++;
}
memset(temp1,1,(temp2-temp1+1)*sizeof(char));
}
else continue;
}
else continue;
}
}
5. (选做题)中序波兰式求解【困难】
(当时脆弱的我选择放弃)
(中序波兰式求解) 请编写程序求解中序波兰式的值。表达式中可能的运算符有+,-,*,/,()。
【输入】中序波兰式
【输出】波兰式的值 //输出的数据类型符合C/C++对表达式求值的定义,即表达式的输出类型由高精度的运算数来决定。
浮点型保留小数点后的3位小数
例如:
【输入】2*(4+5)-12
【输出】6
【输入】2*2.5
【输出】5.000
备注:
(1)对于80%的测试数据运算数中仅仅包含正整数;
(2)对于10%的测试数据运算数中包含有浮点数;
(3)对于10%的测试数据运算数中包含有负数;