中缀表达式转后缀表达式及计算
概述
该程序实现了将中缀表达式转换为后缀表达式,并计算后缀表达式的值。程序首先读取用户输入的中缀表达式,然后将其转换为后缀表达式,并输出转换后的结果。接着,程序要求用户输入一个后缀表达式(可以是之前转换的结果或其他后缀表达式),并计算其值。
数据结构定义
栈结构
栈用来存储运算符,并辅助完成中缀表达式到后缀表达式的转换以及后缀表达式的计算。
typedef struct Stack {
int top; // 栈顶索引
int stack[MAX_SIZE]; // 存储栈元素的数组
} Stack;
基本操作
创建栈
分配内存并初始化栈顶索引为 -1
,表示栈为空。
Stack *createStack() {
Stack *stack = (Stack *)malloc(sizeof(Stack));
stack->top = -1;
return stack;
}
销毁栈
释放栈所占用的内存。
void destroyStack(Stack *stack) {
free(stack);
}
判断栈是否为空
检查栈顶索引是否为 -1
。
int isEmpty(Stack *stack) {
return stack->top == -1;
}
入栈
将元素压入栈顶,如果栈满则输出错误信息并终止程序。
void push(Stack *stack, int value) {
if (stack->top >= MAX_SIZE - 1) {
printf("栈溢出。\n");
exit(1);
}
stack->stack[++stack->top] = value;
}
出栈
弹出栈顶元素,如果栈为空则输出错误信息并终止程序。
int pop(Stack *stack) {
if (isEmpty(stack)) {
printf("栈下溢。\n");
exit(1);
}
return stack->stack[stack->top--];
}
查看栈顶元素
返回栈顶元素,如果栈为空则输出错误信息并终止程序。
int peek(Stack *stack) {
if (isEmpty(stack)) {
printf("栈为空。\n");
exit(1);
}
return stack->stack[stack->top];
}
获取运算符的优先级
根据运算符返回对应的优先级。
int getPrecedence(char op) {
if (op == '+' || op == '-') return 1;
if (op == '*' || op == '/') return 2;
return 0;
}
中缀表达式转后缀表达式
遍历中缀表达式,根据运算符和括号的不同情况,将中缀表达式转换为后缀表达式。
void infixToPostfix(char *infix, char *postfix) {
Stack *stack = createStack();
int i = 0, j = 0;
while (infix[i] != '\0') {
if (isdigit(infix[i])) {
postfix[j++] = infix[i++];
} else if (infix[i] == '(') {
push(stack, infix[i++]);
} else if (infix[i] == ')') {
while (!isEmpty(stack) && peek(stack) != '(') {
postfix[j++] = (char)pop(stack);
}
if (!isEmpty(stack) && peek(stack) == '(') {
pop(stack);
i++;
}
} else {
while (!isEmpty(stack) && getPrecedence((char)peek(stack)) >= getPrecedence(infix[i])) {
postfix[j++] = (char)pop(stack);
}
push(stack, infix[i++]);
}
}
while (!isEmpty(stack)) {
postfix[j++] = (char)pop(stack);
}
postfix[j] = '\0';
destroyStack(stack);
}
计算后缀表达式的值
遍历后缀表达式,根据不同的运算符执行相应的操作。
int evaluatePostfix(char *postfix) {
Stack *stack = createStack();
int i = 0;
while (postfix[i] != '\0') {
if (isdigit(postfix[i])) {
push(stack, postfix[i] - '0');
i++;
} else {
int val2 = pop(stack);
int val1 = pop(stack);
switch (postfix[i++]) {
case '+':
push(stack, val1 + val2);
break;
case '-':
push(stack, val1 - val2);
break;
case '*':
push(stack, val1 * val2);
break;
case '/':
push(stack, val1 / val2);
break;
}
}
}
int result = pop(stack);
destroyStack(stack);
return result;
}
示例代码解析
以下是一个简单的程序示例,演示了如何使用上述定义的栈来转换中缀表达式为后缀表达式,并计算后缀表达式的值:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_SIZE 100
// 定义栈结构
typedef struct Stack {
int top; // 栈顶索引
int stack[MAX_SIZE]; // 存储栈元素的数组
} Stack;
// 创建一个新的栈
Stack *createStack() {
Stack *stack = (Stack *)malloc(sizeof(Stack)); // 分配内存
stack->top = -1; // 初始化栈顶索引为 -1,表示栈为空
return stack;
}
// 销毁栈
void destroyStack(Stack *stack) {
free(stack); // 释放栈所占用的内存
}
// 判断栈是否为空
int isEmpty(Stack *stack) {
return stack->top == -1; // 如果栈顶索引为 -1,则栈为空
}
// 入栈操作
void push(Stack *stack, int value) {
if (stack->top >= MAX_SIZE - 1) { // 如果栈满
printf("栈溢出。\n");
exit(1); // 终止程序
}
stack->stack[++stack->top] = value; // 将值压入栈顶
}
// 出栈操作
int pop(Stack *stack) {
if (isEmpty(stack)) { // 如果栈为空
printf("栈下溢。\n");
exit(1); // 终止程序
}
return stack->stack[stack->top--]; // 返回栈顶元素,并将栈顶索引减一
}
// 查看栈顶元素
int peek(Stack *stack) {
if (isEmpty(stack)) { // 如果栈为空
printf("栈为空。\n");
exit(1); // 终止程序
}
return stack->stack[stack->top]; // 返回栈顶元素
}
// 获取运算符的优先级
int getPrecedence(char op) {
if (op == '+' || op == '-') return 1; // 加号和减号的优先级为 1
if (op == '*' || op == '/') return 2; // 乘号和除号的优先级为 2
return 0; // 非运算符的优先级为 0
}
// 将中缀表达式转换为后缀表达式
void infixToPostfix(char *infix, char *postfix) {
Stack *stack = createStack(); // 创建一个新的栈
int i = 0, j = 0; // 初始化索引
while (infix[i] != '\0') { // 遍历中缀表达式
if (isdigit(infix[i])) { // 如果当前字符是数字
postfix[j++] = infix[i++]; // 将数字添加到后缀表达式
} else if (infix[i] == '(') { // 如果当前字符是左括号
push(stack, infix[i++]); // 将左括号压入栈
} else if (infix[i] == ')') { // 如果当前字符是右括号
while (!isEmpty(stack) && peek(stack) != '(') { // 弹出栈中的运算符直到左括号
postfix[j++] = (char)pop(stack); // 将运算符添加到后缀表达式
}
if (!isEmpty(stack) && peek(stack) == '(') { // 如果栈顶是左括号
pop(stack); // 弹出左括号
i++; // 移动到下一个字符
}
} else { // 如果当前字符是运算符
while (!isEmpty(stack) && getPrecedence((char)peek(stack)) >= getPrecedence(infix[i])) { // 如果栈顶运算符优先级更高或相等
postfix[j++] = (char)pop(stack); // 将栈顶运算符添加到后缀表达式
}
push(stack, infix[i++]); // 将当前运算符压入栈
}
}
while (!isEmpty(stack)) { // 将剩余的运算符从栈中弹出并添加到后缀表达式
postfix[j++] = (char)pop(stack);
}
postfix[j] = '\0'; // 添加字符串结束符
destroyStack(stack); // 销毁栈
}
// 计算后缀表达式的值
int evaluatePostfix(char *postfix) {
Stack *stack = createStack(); // 创建一个新的栈
int i = 0; // 初始化索引
while (postfix[i] != '\0') { // 遍历后缀表达式
if (isdigit(postfix[i])) { // 如果当前字符是数字
push(stack, postfix[i] - '0'); // 将数字转换为整数并压入栈
i++; // 移动到下一个字符
} else { // 如果当前字符是运算符
int val2 = pop(stack); // 弹出第二个操作数
int val1 = pop(stack); // 弹出第一个操作数
switch (postfix[i++]) { // 根据运算符执行相应的操作
case '+':
push(stack, val1 + val2); // 加法
break;
case '-':
push(stack, val1 - val2); // 减法
break;
case '*':
push(stack, val1 * val2); // 乘法
break;
case '/':
push(stack, val1 / val2); // 除法
break;
}
}
}
int result = pop(stack); // 最终结果位于栈顶
destroyStack(stack); // 销毁栈
return result; // 返回结果
}
int main() {
char infixExpression[MAX_SIZE]; // 用于存储中缀表达式
char postfixExpression[MAX_SIZE]; // 用于存储后缀表达式
printf("请输入一个中缀表达式: "); // 提示输入中缀表达式
fgets(infixExpression, MAX_SIZE, stdin); // 读取一行输入
infixExpression[strcspn(infixExpression, "\n")] = 0; // 移除换行符
infixToPostfix(infixExpression, postfixExpression); // 调用函数将中缀表达式转换为后缀表达式
printf("中缀表达式: %s\n", infixExpression); // 输出中缀表达式
printf("后缀表达式: %s\n", postfixExpression); // 输出后缀表达式
char inputPostfix[MAX_SIZE]; // 用于存储输入的后缀表达式
printf("请输入后缀表达式进行计算: "); // 提示输入后缀表达式
fgets(inputPostfix, MAX_SIZE, stdin); // 读取一行输入
inputPostfix[strcspn(inputPostfix, "\n")] = 0; // 移除换行符
int result = evaluatePostfix(inputPostfix); // 调用函数计算后缀表达式的值
printf("结果: %d\n", result); // 输出结果
return 0;
}
注意事项
- 内存管理:确保正确释放分配给栈的内存,避免内存泄漏。
- 边界条件处理:检查栈是否为空或满的情况,避免越界访问。
- 输入验证:对于用户输入进行适当的验证,确保程序的健壮性。