设计一个算术表达式求值程序,要求按照算术运算优先级顺序完成包含加、减、乘、除、乘方、括号的基本整数表达式运算。此处运算数可以是1位长度,也可以是多位长度。输入表达式后依次输出在求值过程中运算数栈内的栈顶数据变化过程,并最终输出表达式值。 例如: 输入: 10+(3+2)^4 输出: 操作数栈栈顶元素变化: 10 3 2 5 4 625 635 表达式值:635 要求:(1)阐述算法使用的主要数据结构与实现的基本思路; (2)给出具体c语言编码及代码注释与运行结果; (3)请分析算法时间复杂度和空间复杂度。
时间: 2024-01-21 16:19:23 浏览: 78
主要数据结构:栈
基本思路:
1. 初始化两个栈:一个操作数栈和一个运算符栈。
2. 从左到右扫描表达式,遇到数字直接入操作数栈,遇到运算符则与运算符栈顶元素比较优先级,如果优先级高于或等于栈顶运算符则入栈,否则将栈顶运算符弹出并将它作用于栈顶的两个操作数,然后将运算结果压入操作数栈,继续比较新的栈顶运算符和当前运算符,直到当前运算符可以入栈为止。
3. 如果扫描到的是左括号,则直接入运算符栈。如果是右括号,则将运算符栈中的运算符弹出并作用于操作数栈中的操作数,直到遇到左括号为止。
4. 最后将操作数栈中的所有操作数依次弹出并相加(或相减),即可得到表达式的值。
具体c语言编码及代码注释与运行结果如下:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define MAX_SIZE 100 // 定义栈的最大容量
// 操作数栈
typedef struct {
int data[MAX_SIZE]; // 栈的数据
int top; // 栈顶指针
} OperandStack;
// 运算符栈
typedef struct {
char data[MAX_SIZE]; // 栈的数据
int top; // 栈顶指针
} OperatorStack;
// 初始化操作数栈
void initOperandStack(OperandStack *stack) {
stack->top = -1;
}
// 判断操作数栈是否为空
int isOperandStackEmpty(OperandStack *stack) {
return stack->top == -1;
}
// 判断操作数栈是否已满
int isOperandStackFull(OperandStack *stack) {
return stack->top == MAX_SIZE - 1;
}
// 向操作数栈中压入一个操作数
void pushOperand(OperandStack *stack, int operand) {
if (isOperandStackFull(stack)) {
printf("Operand stack overflow!\n");
exit(1);
}
stack->data[++stack->top] = operand;
}
// 从操作数栈顶弹出一个操作数
int popOperand(OperandStack *stack) {
if (isOperandStackEmpty(stack)) {
printf("Operand stack underflow!\n");
exit(1);
}
return stack->data[stack->top--];
}
// 获取操作数栈顶元素
int getTopOperand(OperandStack *stack) {
if (isOperandStackEmpty(stack)) {
printf("Operand stack underflow!\n");
exit(1);
}
return stack->data[stack->top];
}
// 初始化运算符栈
void initOperatorStack(OperatorStack *stack) {
stack->top = -1;
}
// 判断运算符栈是否为空
int isOperatorStackEmpty(OperatorStack *stack) {
return stack->top == -1;
}
// 判断运算符栈是否已满
int isOperatorStackFull(OperatorStack *stack) {
return stack->top == MAX_SIZE - 1;
}
// 向运算符栈中压入一个运算符
void pushOperator(OperatorStack *stack, char op) {
if (isOperatorStackFull(stack)) {
printf("Operator stack overflow!\n");
exit(1);
}
stack->data[++stack->top] = op;
}
// 从运算符栈顶弹出一个运算符
char popOperator(OperatorStack *stack) {
if (isOperatorStackEmpty(stack)) {
printf("Operator stack underflow!\n");
exit(1);
}
return stack->data[stack->top--];
}
// 获取运算符栈顶元素
char getTopOperator(OperatorStack *stack) {
if (isOperatorStackEmpty(stack)) {
printf("Operator stack underflow!\n");
exit(1);
}
return stack->data[stack->top];
}
// 判断一个字符是否是运算符
int isOperator(char ch) {
return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^' || ch == '(' || ch == ')';
}
// 判断两个运算符的优先级
int getPriority(char op1, char op2) {
int p1, p2;
switch (op1) {
case '+':
case '-':
p1 = 1;
break;
case '*':
case '/':
p1 = 2;
break;
case '^':
p1 = 3;
break;
case '(':
p1 = 0;
break;
}
switch (op2) {
case '+':
case '-':
p2 = 1;
break;
case '*':
case '/':
p2 = 2;
break;
case '^':
p2 = 4;
break;
case '(':
p2 = 5;
break;
case ')':
p2 = 0;
break;
}
return p1 >= p2;
}
// 计算一个算术表达式的值
int calculate(char *expr) {
OperandStack operandStack; // 操作数栈
OperatorStack operatorStack; // 运算符栈
initOperandStack(&operandStack);
initOperatorStack(&operatorStack);
int i = 0;
while (expr[i] != '\0') {
if (isdigit(expr[i])) { // 数字直接入操作数栈
int operand = 0;
while (isdigit(expr[i])) {
operand = operand * 10 + (expr[i] - '0');
i++;
}
pushOperand(&operandStack, operand); // 将操作数压入操作数栈
printf("Operand stack top: %d\n", getTopOperand(&operandStack));
} else if (isOperator(expr[i])) { // 运算符
if (expr[i] == '(') { // 左括号直接入运算符栈
pushOperator(&operatorStack, expr[i]);
} else if (expr[i] == ')') { // 右括号弹出运算符栈中的运算符直到遇到左括号
while (getTopOperator(&operatorStack) != '(') {
int operand2 = popOperand(&operandStack);
int operand1 = popOperand(&operandStack);
char op = popOperator(&operatorStack);
int result;
switch (op) {
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '/':
result = operand1 / operand2;
break;
case '^':
result = pow(operand1, operand2);
break;
}
pushOperand(&operandStack, result);
printf("Operand stack top: %d\n", getTopOperand(&operandStack));
}
popOperator(&operatorStack); // 弹出左括号
} else { // 其他运算符比较优先级后入运算符栈
while (!isOperatorStackEmpty(&operatorStack) && getPriority(getTopOperator(&operatorStack), expr[i])) {
int operand2 = popOperand(&operandStack);
int operand1 = popOperand(&operandStack);
char op = popOperator(&operatorStack);
int result;
switch (op) {
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '/':
result = operand1 / operand2;
break;
case '^':
result = pow(operand1, operand2);
break;
}
pushOperand(&operandStack, result);
printf("Operand stack top: %d\n", getTopOperand(&operandStack));
}
pushOperator(&operatorStack, expr[i]); // 将当前运算符入运算符栈
}
i++;
} else { // 非法字符
printf("Invalid character: %c\n", expr[i]);
exit(1);
}
}
// 扫描完表达式后,弹出运算符栈中的所有运算符并作用于操作数栈中的操作数
while (!isOperatorStackEmpty(&operatorStack)) {
int operand2 = popOperand(&operandStack);
int operand1 = popOperand(&operandStack);
char op = popOperator(&operatorStack);
int result;
switch (op) {
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '/':
result = operand1 / operand2;
break;
case '^':
result = pow(operand1, operand2);
break;
}
pushOperand(&operandStack, result);
printf("Operand stack top: %d\n", getTopOperand(&operandStack));
}
return getTopOperand(&operandStack); // 返回操作数栈中剩余的操作数
}
int main() {
char expr[MAX_SIZE];
printf("Enter an arithmetic expression: ");
scanf("%s", expr);
int result = calculate(expr);
printf("Result: %d\n", result);
return 0;
}
```
运行结果:
```
Enter an arithmetic expression: 10+(3+2)^4
Operand stack top: 10
Operand stack top: 3
Operand stack top: 2
Operand stack top: 5
Operand stack top: 4
Operand stack top: 625
Operand stack top: 635
Result: 635
```
算法时间复杂度:该算法的时间复杂度与表达式的长度有关,需要扫描整个表达式一遍,而每个字符最多进出两个栈,因此时间复杂度为O(n),其中n为表达式的长度。
算法空间复杂度:该算法需要使用两个栈,其空间复杂度与表达式中运算符和括号的数量有关,最坏情况下为O(n),其中n为表达式的长度。
阅读全文