数据结构之栈与队列:栈实现四则运算表达式的求值(C & Python)

本文详细介绍了如何使用栈(包括整型栈和字符栈)结合优先级数组,实现C语言和Python中四则运算表达式的求值过程。通过实例演示了操作符优先级处理和栈的动态管理,适合初学者理解栈在算法中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1   程序设计

为了实现用栈计算算数表达式的值,需设置两个工作栈:用于存储运算符的栈operandStack,以及用于存储操作数及中间结果的栈operatorStack。

算法基本思想如下:

1)首先将操作数栈operandStack设为空栈,而将'#'作为运算符栈operatorStack的栈底元素,这样的目的是判断表达式是否求值完毕。

2)依次读入表达式的每个字符,表达式须以'#'结尾,若是操作数则入栈operandStack,若是运算符,则将此运算符c与operatorStack的栈顶元素top比较优先级后执行相应的操作,具体操作如下:

①若top的优先级小于c,即top<c,则将c直接入栈operatorStack,并读入下一字符赋值给c;

②若top的优先级等于c,即top=c,则弹出operatorStack的栈顶元素,并读入下一字符赋值给c,这一步目的是进行括号操作;

③若top优先级高于c,即top>c,则表明可以计算,此时弹出operandStack的栈顶两个元素,并且弹出operatorStack栈顶的的运算符,计算后将结果放入占operandStack中,然后继续比较top和c的优先级,直至top不大于c。

④重复①②③直至operatorStack栈空,此时求值结束。

算符间的优先关系如下表所示:

表中需要注意的是θ1为opter的栈顶元素,θ2位从表达式中读取的操作符,此优先级表可以用二维数组实现。

2   C语言实现

代码:

相关变量

#include <stdlib.h>
#include <stdio.h>
 
#define STACK_INIT_SIZE 100   //栈初始开辟空间大小
#define STACK_INCREMENT 10    //栈追加空间大小

//优先级数组,2表示top>c,1表示top<c,0表示top=c,-1表示错误
int prior[7][7] = {{2,2,1,1,1,2,2},{2,2,1,1,1,2,2},{2,2,2,2,1,2,2},
{2,2,2,2,1,2,2},{1,1,1,1,1,0,-1},{2,2,2,2,-1,2,2},{1,1,1,1,1,-1,0}};

 栈的实现

//******************************************************************
//                           整形栈的实现
//******************************************************************

//整形栈结构体
typedef struct {
    int *base;
    int *top;
    int size;
}intStack;


//栈初始化
intStack intStack_init()
{
    intStack s;
    s.base = (int *)malloc(sizeof(int)*STACK_INIT_SIZE);
    s.top = s.base;
    s.size = STACK_INIT_SIZE;
    return s;
}
 
//入栈
void intPush(intStack *s, int e)
{
    if(s->top - s->base >= s->size)
    {
        s->size += STACK_INCREMENT;
        s->base = realloc(s->base, sizeof(int)*s->size);
    }
    *s->top = e;
    s->top++;
}
 
//出栈
int intPop(intStack *s)
{
    if(s->top != s->base)
    {
        s->top--;
        return *s->top;
    }
    return -1;
}


//******************************************************************
//                         字符栈的实现
//******************************************************************

//字符栈结构体
typedef struct {
    char *base;
    char *top;
    int size;
}charStack;


//栈初始化
charStack charStack_init()
{
    charStack s;
    s.base = (char *)malloc(sizeof(char)*STACK_INIT_SIZE);
    s.top = s.base;
    s.size = STACK_INIT_SIZE;
    return s;
}
 
//入栈
void charPush(charStack *s, char e)
{
    if(s->top - s->base >= s->size)
    {
        s->size += STACK_INCREMENT;
        s->base = realloc(s->base, sizeof(char)*s->size);
    }
    *s->top = e;
    s->top++;
}
 
//出栈
char charPop(charStack *s)
{
    if(s->top != s->base)
    {
        s->top--;
        return *s->top;
    }
    return -1;
}

//得到栈顶元素,但不出栈
char getTop(charStack *s)
{
    s->top--;
    char temp = *s->top;
    s->top++;
    return temp;
}

求解表达式

//******************************************************************
//                      使用栈结构求解表达式
//******************************************************************

//得到操作符在数组prior中的索引值
int getIndex(char operator)
{
    switch(operator)
    {
        case '+' : return 0;
        case '-' : return 1;
        case '*' : return 2;
        case '/' : return 3;
        case '(' : return 4;
        case ')' : return 5;
        case '#' : return 6;
    }
}

//求得两个操作数和一个操作符的运算结果
int compute(int operand1, int operand2, char operator)
{
    switch(operator)
    {
        case '+' : return operand1 + operand2;
        case '-' : return operand1 - operand2;
        case '*' : return operand1 * operand2;
        case '/' : return operand1 / operand2;
    }
}

//由表达式字符串指针,得到下一个操作符或操作数
//得到操作符标记key=0,得到操作数标记key=1
//返回偏移后的字符串指针
char *operand_or_operator(char *p, int *operand, char *operator, int *key)
{
    while(*p == ' ') p++;               //跳过空格
    if(*p >= '0' && *p <= '9')          //得到操作数
    {
        *operand = 0;
        int dec = 1;                    //十进制数位权重
        intStack s = intStack_init();   //使用整形栈转化数值        
        while(*p >= '0' && *p <= '9')   //操作数位由高到低依次压入栈中
        {
            intPush(&s, *p - '0');
            p++;
        }
        while(s.base != s.top)          //依次读取栈中操作数各位
        {
            *operand += intPop(&s) * dec;
            dec *= 10;
        }
        *key = 1;  
    } 
    else                               //得到操作符
    {
        switch(*p)
        {
            case '+' :*operator = '+';break;
            case '-' :*operator = '-';break;
            case '*' :*operator = '*';break;
            case '/' :*operator = '/';break;
            case '(' :*operator = '(';break;
            case ')' :*operator = ')';break;
            case '#' :*operator = '#';break;          
        }
        p++;
        *key = 0;
    }
    return p;
}

//由表达式字符串得到最终计算结果
int output(char *p)
{
    intStack operandStack = intStack_init();     //初始化操作数栈
    charStack operatorStack = charStack_init();  //初始化操作符栈
    charPush(&operatorStack, '#');
    int operand, key, index1, index2;
    char operator;
    while(operatorStack.base != operatorStack.top)  //操作符栈空代表计算结束
    {
        p = operand_or_operator(p, &operand, &operator, &key);
        if(key)  //得到操作数
            intPush(&operandStack, operand);
        else     //得到操作符
        {
            index1 = getIndex(getTop(&operatorStack));
            index2 = getIndex(operator);
            while(prior[index1][index2] == 2)   //top优先级高于c
            {
                intPush(&operandStack, compute(intPop(&operandStack), intPop(&operandStack), charPop(&operatorStack)));
                index1 = getIndex(getTop(&operatorStack));
            }
            if(prior[index1][index2] == 1)      //top优先级低于c
            {
               charPush(&operatorStack, operator); 
            }
            else if(prior[index1][index2] == 0) //top优先级等于c
            {
                charPop(&operatorStack);
            }
            else
            {
                printf("Enter Error!!!\n");
                return 0XFFFFFFFF;
            }
        }
    }
    return intPop(&operandStack);
}

主函数

//******************************************************************
//                              主函数
//******************************************************************

void main()
{
    char str[100];
    int out;
    printf("\n请输入规范的四则运算表达式,以#结尾:\n");
    scanf("%s", str);
    out = output(str);
    if(out != 0XFFFFFFFF)
        printf("结果等于:\n%d\n\n", out);
    system("date /T");
    system("TIME /T");
    system("pause");
    exit(0);      
}

运行结果:

3   Python实现

代码:

#coding=gbk

import datetime
import time
from pip._vendor.distlib.compat import raw_input 


#优先级列表
prior = [[2,2,1,1,1,2,2], [2,2,1,1,1,2,2], [2,2,2,2,1,2,2], 
         [2,2,2,2,1,2,2], [1,1,1,1,1,0,-1], [2,2,2,2,-1,2,2], [1,1,1,1,1,-1,0]]


#########################################################################################
#                                    栈类
#########################################################################################
class Stack:
    def __init__(self):
        self._s = []
    
    def push(self, e):
        self._s.append(e)
        
    def pop(self):
        if self._s:
            return self._s.pop()
        else:
            raise LookupError("stack is empty!")
    
    def isEmpty(self):
        return bool(self._s)
    
    def getTop(self):
        return self._s[-1]
    


#########################################################################################
#                                   表达式求值函数模块
#########################################################################################

#由操作符得到优先级列表索引值
def getIndex(operator):
    var = 0
    if operator == '+':
        var = 0
    elif operator == '-':
        var = 1
    elif operator == '*':
        var = 2
    elif operator == '/':
        var = 3
    elif operator == '(':
        var = 4
    elif operator == ')':
        var = 5
    elif operator == '#':
        var = 6
    return var

#得到一个操作符作用于两个操作数的结果    
def compute(operand2, operand1, operator):
    var = 0
    if operator == '+':
        var = operand1 + operand2
    elif operator == '-':
        var = operand1 - operand2
    elif operator == '*':
        var = operand1 * operand2
    elif operator == '/':
        var = operand1 / operand2
    return var

#由表达式字符串和索引值得到下一个操作数或操作符
#函数返回3元列表,list[0]是操作数或操作符,list[1]是偏移后的索引值
#list[3]是标记值,返回操作符标记0,返回操作数返回1    
def operand_or_operator(string, index):
    var = []
    while string[index] == ' ':
        index += 1
    if string[index] in ['+', '-', '*', '/', '(', ')', '#']:
        var = [string[index], index+1, 0]
    elif string[index] in [str(x) for x in range(0, 10)]:
        temp = index
        while string[index] in [str(x) for x in range(0, 10)]:
            index += 1
        var = [int(string[temp:index]), index, 1]
    return var

#由表达式字符串得到最终结果    
def output(string):
    operandStack = Stack()    #操作数栈
    operatorStack = Stack()   #操作符栈
    operatorStack.push('#')
    index = 0
    while operatorStack._s != []:                    #操作符栈空计算结束
        value = operand_or_operator(string, index)
        if value[2] == 1:     #得到操作数
            operandStack.push(value[0])
        elif value[2] == 0:   #得到操作符
            index1 = getIndex(operatorStack.getTop())
            index2 = getIndex(value[0])
            while prior[index1][index2] == 2:  #top>c
                operandStack.push(compute(operandStack.pop(),operandStack.pop(),operatorStack.pop()))
                index1 = getIndex(operatorStack.getTop())
            if prior[index1][index2] == 1:     #top<c
                operatorStack.push(value[0])
            elif prior[index1][index2] == 0:   #top=c
                operatorStack.pop()
            else:                              #输入错误
                return 0XFFFFFFFF
        index = value[1]
    return operandStack.pop()



########################################################################################
#                                      主模块
########################################################################################
if __name__ == '__main__':
    string = input("\n请输入规范的四则运算表达式,以#结束:\n")
    out = output(string)
    if out == 0XFFFFFFFF:
        print("Enter Error!!!")
    else:
        print("结果等于:\n{}\n\n".format(out))
    datetime = datetime.datetime.now()
    print(datetime.strftime("%Y-%m-%d\n%H:%M:%S"))
    input("Press Enter to exit…")     

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

观察者555

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值