2024/11/19日 日志 数据结构实验(2)---栈实现表达式求值、队列应用(蓝桥杯)
栈实现表达式求值
问题:https://pintia.cn/problem-sets/1858366427985383424/exam/problems/type/7?problemSetProblemId=1858366732315615232
解答:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
//运算符优先级
int precedence(char op) {
switch (op) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}
//转换为后缀表达式
int infixToPostfix(const string& infix, string& postfix) {
stack<char>s;
bool prevWasOp = true; //前一个字符是否是运算符
int openPar = 0; //开括号数量
for (char c : infix) {
if (isspace(c)) {
continue;//跳过空格
}
if (isdigit(c)) {
if (!prevWasOp) {
return -2;//表达式缺操作数
}
postfix += c;//直接将数字加入后缀表达式
prevWasOp = false;//当前为操作数
}
else if (c == '(') {
s.push(c);
openPar++;
prevWasOp = true;
}
else if (c == ')') {
while (!s.empty() && s.top() != '(') {
postfix += s.top();
s.pop();
}
if (s.empty()) {
return -1;//缺少右括号
}
s.pop();//弹出'('
openPar--;
prevWasOp = false; //')'后面可以是运算符
}else {
if (precedence(c) == 0) {
//无效字符
}
if (prevWasOp) {
return -2;//表达式缺少操作数
}
while (!s.empty() && precedence(s.top()) >= precedence(c)) {
postfix += s.top();
s.pop();
}
s.push(c);
prevWasOp = true;//当前是运算符
}
}
while (!s.empty()) {
char top = s.top();
if (top == '(') {
return -1;//缺少右括号
}
postfix += top;
s.pop();
}
return openPar > 0 ? -1: 0;
}
//计算后缀表达式的值
int evaluatePost(const string& postfix) {
stack<int>s;
for (char c : postfix) {
if (isdigit(c)) {
s.push(c - '0');//将字符数字转换为整数
}
else {
int b = s.top();
s.pop();
int a = s.top();
s.pop();
switch (c) {
case '+':s.push(a + b); break;
case '-':s.push(a - b); break;
case '*':s.push(a * b); break;
case '/':s.push(a / b); break;
}
}
}
return s.top();
}
int main() {
string in;
string post;
getline(cin,in);
int result = infixToPostfix(in, post);
if (result == -1) {
cout << "ERROR:缺少括号"<<endl;
}
else if (result == -2) {
cout << "ERROR:表达式缺操作数" << endl;
}
else {
cout << post << endl;
int value = evaluatePost(post);
cout << value ;
}
return 0;
}
点击查看代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXSIZE 100
typedef struct {
char data[MAXSIZE];
int top;
} Stack;
// 栈操作
void initStack(Stack *s) {
s->top = -1;
}
int isEmpty(Stack *s) {
return s->top == -1;
}
int isFull(Stack *s) {
return s->top == MAXSIZE - 1;
}
void push(Stack *s, char c) {
if (!isFull(s)) {
s->data[++(s->top)] = c;
}
}
char pop(Stack *s) {
if (!isEmpty(s)) {
return s->data[(s->top)--];
}
return '\0'; // 空栈时返回空字符
}
char peek(Stack *s) {
if (!isEmpty(s)) {
return s->data[s->top];
}
return '\0'; // 空栈时返回空字符
}
// 运算符优先级
int precedence(char op) {
switch (op) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}
// 转换为后缀表达式
int infixToPostfix(const char *infix, char *postfix) {
Stack s;
initStack(&s);
int j = 0;
int prevWasOperator = 1; // 表示前一个字符是否是运算符
int openParentheses = 0; // 记录开括号数量
for (int i = 0; infix[i] != '\0'; i++) {
char c = infix[i];
if (isspace(c)) {
continue; // 跳过空格
}
if (isdigit(c)) {
if (!prevWasOperator) {
return -2; // 表达式缺操作数
}
postfix[j++] = c; // 直接将数字加入后缀表达式
prevWasOperator = 0; // 当前是操作数
} else if (c == '(') {
push(&s, c);
openParentheses++;
prevWasOperator = 1; // '('后面可以是操作数
} else if (c == ')') {
while (!isEmpty(&s) && peek(&s) != '(') {
postfix[j++] = pop(&s);
}
if (isEmpty(&s)) {
return -1; // 缺少右括号
}
pop(&s); // 弹出 '('
openParentheses--;
prevWasOperator = 0; // ')'后面可以是运算符
} else {
if (precedence(c) == 0) {
return -3; // 无效字符
}
if (prevWasOperator) {
return -2; // 表达式缺操作数
}
while (!isEmpty(&s) && precedence(peek(&s)) >= precedence(c)) {
postfix[j++] = pop(&s);
}
push(&s, c);
prevWasOperator = 1; // 当前是运算符
}
}
while (!isEmpty(&s)) {
char top = pop(&s);
if (top == '(') {
return -1; // 缺少右括号
}
postfix[j++] = top;
}
postfix[j] = '\0'; // 结束后缀表达式
return openParentheses > 0 ? -1 : 0; // 确保所有括号匹配
}
// 计算后缀表达式的值
int evaluatePostfix(const char *postfix) {
Stack s;
initStack(&s);
for (int i = 0; postfix[i] != '\0'; i++) {
char c = postfix[i];
if (isdigit(c)) {
push(&s, c - '0'); // 将字符数字转换为整数
} else {
int b = pop(&s);
int a = pop(&s);
switch (c) {
case '+': push(&s, a + b); break;
case '-': push(&s, a - b); break;
case '*': push(&s, a * b); break;
case '/': push(&s, a / b); break;
}
}
}
return pop(&s); // 返回最终结果
}
int main() {
char infix[MAXSIZE];
char postfix[MAXSIZE];
printf("请输入数学表达式: ");
fgets(infix, MAXSIZE, stdin);
int result = infixToPostfix(infix, postfix);
if (result == -1) {
printf("ERROR:缺少括号\n");
} else if (result == -2) {
printf("ERROR:表达式缺操作数\n");
} else if (result == -3) {
printf("ERROR:无效字符\n");
} else {
printf("后缀表达式: %s\n", postfix);
int value = evaluatePostfix(postfix);
printf("结果: %d\n", value);
}
return 0;
}
队列应用(蓝桥杯)
题目:https://pintia.cn/problem-sets/1858366427985383424/exam/problems/type/7?problemSetProblemId=1858366732315615233
解答:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAXM = 1005;
int M;
string inflx[MAXM];
vector<string>post;
queue<string> vip;
queue<string> nor;
void queueup(const string *inflx) {
for (int i = 1; i <= M; i++) {
string in = inflx[i];
if (in.substr(0, 3) == "IN ") {
string name = in.substr(3);
char type = name.back();
name.pop_back(); //删除末尾类型
name.pop_back();//删除空格
if (type == 'V') {
vip.push(name);
}
else if (type == 'N') {
nor.push(name);
}
}else if (in.substr(0, 4) == "OUT ") {
char type = in[4];
if (type == 'V' && !vip.empty()) {
vip.pop();
}
else if (type == 'N' &&!nor.empty()) {
nor.pop();
}
}
}
}
int main() {
cin >> M;
cin.ignore();
for (int i = 1; i <= M; i++) {
getline(cin, inflx[i]);
}
queueup(inflx);
while (!vip.empty()) {
post.emplace_back(vip.front());
vip.pop();
}
while (!nor.empty()) {
post.emplace_back(nor.front());
nor.pop();
}
for (int i = 0; i < post.size(); i++) {
cout << post[i];
if (i != post.size() - 1) {
cout << endl;
}
}
return 0;
}
补充:https://blog.csdn.net/qq_47332831/article/details/123400882
补:
关于栈定义:
typedef int STDataType; // 定义数据类型
typedef struct Stack
{
STDataType* a; // 定义一个动态数组
STDataType top; // 用来确定栈顶位置(指向栈顶元素的下一个位置)
STDataType capacity; // 栈的容量
}ST; // ST 为结构体的缩写名
关于队列定义:
typedef int QDataType;
typedef struct QueueNode
{
QDataType _data; //用来存储数据
struct QueueNode* _next;//用来指向下一个结构体
}QueueNode;
typedef struct Queue
{
QueueNode* _head; //存放整个队列的队头
QueueNode* _tail; //存放整个队列的队尾
}Queue;