表达式求值

github仓库:https://github.com/EanoJiang/Data-structures-and-algorithms

栈——表达式求值

1744613611721

枚举

typedef enum{
	枚举元素;
}枚举名;

后缀表达式运算逻辑

遇到数字入栈,遇到符号出栈运算,运算结果入栈,\0结束

1744769674147

1744769687104

1744769713985

#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;
#define MAXSIZE 100

typedef struct Stack{
    int top;
    ElemType *data;
}Stack;


// 初始化栈
Stack* initStack(){
    Stack *s = (Stack*)malloc(sizeof(Stack));
    s->data = (ElemType*)malloc(MAXSIZE * sizeof(ElemType));
    s->top = -1;
    return s;
}

int isEmpty(Stack* s){
    return s->top == -1;
}

//入栈
int push(Stack *s, ElemType e){
    if(s->top == MAXSIZE-1){
        printf("栈满\n");
        return 0;
    }
    s->top++;
    //从栈顶入栈
    s->data[s->top] = e;
    return 1;
}

//出栈
ElemType pop(Stack *s,ElemType *e){
    if(s->top == -1){
        printf("栈空\n");
        return 0;
    }
    *e = s->data[s->top];
    s->top--;
    return *e;
}

//查看栈顶元素
ElemType getTop(Stack *s,ElemType *e){
    if(s->top == -1){
        printf("栈空\n");
        return 0;
    }
    *e = s->data[s->top];
    return *e;
}

typedef enum {
    LEFT_PARE,RIGHT_PARE,
    ADD,SUB,MUL,DIV,MOD,
    EOS,NUM
}contentType;

char expr[] = "82/2+56*-";

contentType getToken(char *symbol,int *index){
    //存储当前字符
    *symbol = expr[*index];
    //这句不能写成*index++:指针*index的地址自增
    *index = *index + 1;//指针*index的值自增
    switch(*symbol){
        case '(':
            return LEFT_PARE;
        case ')':
            return RIGHT_PARE;
        case '+':
            return ADD;
        case '-':
            return SUB;
        case '*':
            return MUL;
        case '/':
            return DIV;
        case '%':
            return MOD;
        case '\0':
            return EOS;
        default:
            if(*symbol >= '0' && *symbol <= '9'){
                return NUM;
            }
            else{
                printf("非法字符\n");
                return -1;
            }
    }
}

//计算后缀表达式
int eval(Stack *s){
    char symbol;
    int op1,op2;
    int index = 0;
    ElemType result;
    contentType token;
    token = getToken(&symbol,&index);
    //结束条件\0
    while(token!= EOS){
        //遇到数字
        if(token == NUM){
            //将数字(字符相应ASCII码-'0')压入栈中
            push(s,symbol - '0');
        }
        //遇到操作符
        else{
            //出栈,把被操作数存到op2和op1中
            pop(s,&op2);
            pop(s,&op1);
            //计算结果入栈
            switch(token){
                case ADD:
                    push(s,op1 + op2);
                    break;
                case SUB:
                    push(s,op1 - op2); 
                    break;
                case MUL:
                    push(s,op1 * op2);  
                    break;
                case DIV:
                    push(s,op1 / op2);
                    break;
                case MOD:
                    push(s,op1 % op2);
                    break;
                default:
                    printf("非法字符\n");
                    return 0;
            }
        }
        //更新token
        token = getToken(&symbol,&index);
    }
    //循环结束条件\0后,栈中只有一个元素,出栈并打印
    pop(s,&result);
    printf("结果为:%d\n",result);
    return 1;
}


int main(){
    Stack *s = initStack();
    eval(s);
    return 0;

}


中缀表达式转后缀表达式

1744771900049

1744771980988

1744772007626

1744772089827

1744772165022

1744772184740

#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;
#define MAXSIZE 100

typedef struct Stack{
    int top;
    ElemType *data;
}Stack;


// 初始化栈
Stack* initStack(){
    Stack *s = (Stack*)malloc(sizeof(Stack));
    s->data = (ElemType*)malloc(MAXSIZE * sizeof(ElemType));
    s->top = -1;
    return s;
}

int isEmpty(Stack* s){
    return s->top == -1;
}

//入栈
int push(Stack *s, ElemType e){
    if(s->top == MAXSIZE-1){
        printf("栈满\n");
        return 0;
    }
    s->top++;
    //从栈顶入栈
    s->data[s->top] = e;
    return 1;
}

//出栈
ElemType pop(Stack *s,ElemType *e){
    if(s->top == -1){
        printf("栈空\n");
        return 0;
    }
    *e = s->data[s->top];
    s->top--;
    return *e;
}

//查看栈顶元素
ElemType getTop(Stack *s,ElemType *e){
    if(s->top == -1){
        printf("栈空\n");
        return 0;
    }
    *e = s->data[s->top];
    return *e;
}


typedef enum {
    LEFT_PARE,RIGHT_PARE,
    ADD,SUB,MUL,DIV,MOD,
    EOS,NUM
}contentType;

char expr[] = "x/(i-j)*y";

contentType getToken(char *symbol,int *index){
    //当前字符存到指针symbol中
    *symbol = expr[*index];
    //这句不能写成*index++:指针*index的地址自增
    *index = *index + 1;//指针*index的值自增
    switch(*symbol){
        case '(':
            return LEFT_PARE;
        case ')':
            return RIGHT_PARE;
        case '+':
            return ADD;
        case '-':
            return SUB;
        case '*':
            return MUL;
        case '/':
            return DIV;
        case '%':
            return MOD;
        case '\0':
            return EOS;
        default:
                return NUM;

    }
}

//计算后缀表达式
int eval(Stack *s){
    char symbol;
    int op1,op2;
    int index = 0;
    ElemType result;
    contentType token;
    token = getToken(&symbol,&index);
    //结束条件\0
    while(token!= EOS){
        //遇到数字
        if(token == NUM){
            //将数字(字符相应ASCII码-'0')压入栈中
            push(s,symbol - '0');
        }
        //遇到操作符
        else{
            //出栈,把被操作数存到op2和op1中
            pop(s,&op2);
            pop(s,&op1);
            //计算结果入栈
            switch(token){
                case ADD:
                    push(s,op1 + op2);
                    break;
                case SUB:
                    push(s,op1 - op2); 
                    break;
                case MUL:
                    push(s,op1 * op2);  
                    break;
                case DIV:
                    push(s,op1 / op2);
                    break;
                case MOD:
                    push(s,op1 % op2);
                    break;
                default:
                    printf("非法字符\n");
                    return 0;
            }
        }
        //更新token
        token = getToken(&symbol,&index);
    }
    //循环结束条件\0后,栈中只有一个元素,出栈并打印
    pop(s,&result);
    printf("结果为:%d\n",result);
    return 1;
}

//打印token
int print_token(contentType token)
{
	switch(token)
	{
		case ADD:
			printf("+");
			break;
		case SUB:
			printf("-");
			break;
		case MUL:
			printf("*");
			break;
		case DIV:
			printf("/");
			break;
		case MOD:
			printf("%%");
			break;
		default:
			return 0;
	}
	return 1;
}

//中缀转后缀表达式,打印
void postfix(Stack *s){
    //运算符优先级
    //LEFT_PARE,RIGHT_PARE,ADD,SUB,MUL,DIV,MOD,EOS
    int in_stack[] = {0,19,12,12,13,13,13,0};//栈内运算符(左括号在栈里面的时候优先级是0)
	int out_stack[] = {20, 19, 12, 12, 13, 13, 13, 0};//栈外运算符
    contentType token;
    int index = 0;
    //栈顶先放一个\0,作为优先级最低的token
    s->top = 0;
    s->data[0] = EOS;
    char symbol;
    ElemType e;
  
    token = getToken(&symbol,&index);
    //结束条件\0,就不再获取新的token了
    while(token!= EOS){
        //遇到数字
        if(token == NUM)
        {
            printf("%c",symbol);
        }
        //遇到右括号
        else if(token == RIGHT_PARE){
            //出栈并打印,结束条件:遇到左括号
            while(s->data[s->top] != LEFT_PARE){
                pop(s,&e);
                print_token(e);
            }
            //出栈左括号
            pop(s,&e);
        }
        //遇到其他操作符
        else{
            //优先级越小越优先
            //优先级:当前元素(优先)<=栈顶元素,出栈并打印
            while(out_stack[token] <= in_stack[s->data[s->top]]){
                pop(s,&e);
                print_token(e);
            }
            //优先级:当前元素>栈顶元素(优先),入栈
            push(s,token);
        }
        //更新token
        token = getToken(&symbol,&index);
    }
    //出栈剩余的元素
    pop(s, &e);
    //打印剩余的元素
	token = e;
	while(token != EOS)
	{
		print_token(token);
		pop(s, &e);
		token = e;
	}
	printf("\n");
}

int main(){
    Stack *s = initStack();
    printf("中缀表达式:%s\n",expr);
    postfix(s);
    return 0;
}
posted @ 2025-04-23 09:56  EanoJiang  阅读(25)  评论(0)    收藏  举报