栈的应用:中缀表达式转为后缀表达式(c语言实现)

中缀表达式:

中缀表达式(或中缀记法)是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:3 + 4),中缀表达式是人们常用的算术表示方法。

后缀表达式:

不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2 + 1) * 3 , 即2 1 + 3 *


算法思路:

·开始扫描;
·数字时,加入后缀表达式;
·运算符:
a. 若为 '(',入栈;
b. 若为 ')',则依次把栈中的的运算符出栈,加入后缀表达式中,直到出现'(',从栈中删除'(' ;
c. 若为 除括号外的其他运算符, 当其优先级高于除'('以外的栈顶运算符时,直接入栈。否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到一个比它优先级低的或者遇到了一个左括号为止。
·当扫描的中缀表达式结束时,栈中的的所有运算符出栈;


c语言代码如下:

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


//中缀表达式求值
//先转为后缀表达式再求值;为简单起见,使用栈的循序存储结构实现


//栈的顺序存储结构,用一维数组实现



#define OK 1
#define ERROR -1
#define TRUE 1
#define FALSE 0
#define MAXSIZE 10
typedef int Status;
typedef char ElemType;
typedef struct {
    ElemType data[MAXSIZE];
    int top;//栈顶指针
}Stack;
//1. 初始化
Status InitStack(Stack *S){
    int i;
    for(i=0;i<MAXSIZE;i++)
    S->data[i]=NULL;
    S->top=-1;
    return OK;
}
//2. 创建一个长度为n的堆栈
Status CreateStack(Stack *S,int n){
    if(n>MAXSIZE || n<1){
        printf("输入长度有误!\n");
        return ERROR;
    }
    srand(time(0));
    int i;
    for(i=0;i<n;i++){

        S->data[i]=rand()%100+1;
    }
    S->top=n-1;

    return OK;

}
//3. 压栈操作
Status push(Stack *S,ElemType e){
    if(MAXSIZE-1==S->top){
        printf("栈已满\n");
        return ERROR;
    }
    //栈顶指向的元素有值
    ++(S->top);
    S->data[S->top]=e;
    return OK;
}
//4. 出栈
Status pop(Stack *S,ElemType *e){
//将栈顶元素出栈,传给e
    if(-1==S->top){
        printf("栈为空!\n");
        return ERROR;
    }
    *e=S->data[S->top];
    --(S->top);
    return OK;
}

//5. 中缀表达式转后缀表达式
void MidToFinal(char *mid,char *final){
    //中缀表达式为middle,要转换成后缀表达式传给last
    //新建一个栈,来存储符号
    char e;
    Stack S;
    if(OK!=InitStack(&S)){
        printf("初始化栈失败!\n");

    }
    //当带转换的字符串*mid未终止时,循环处理
    while(*mid){

            //如果是数字,则直接输出
        if(*mid>='0' && *mid<='9'){
            *(final++)=*(mid++);
            continue;
        }else if(*mid=='+' || *mid=='-' || *mid=='*' || *mid=='/' || *mid=='(' || *mid==')'){

            //输入的是合法运算符号,比较之前是否有更高优先级的符号
            if(S.top==-1 || '('==*mid){
                //当符号栈为空或遇到左括号时,符号入栈
                push(&S,*(mid++));
                continue;
            }
            if(')'==*mid){
                //遇到右括号时,栈顶元素依次出栈;直到遇到第一个左括号时结束
                pop(&S,&e);
                *(final++)=e;
                while(pop(&S,&e) && e!='('){
                    *(final++)=e;
                }
               // printf("%c\n",e);
                mid++;

                continue;
            }
            //后续的处理都要取出临时的栈顶元素,与当前输入的符号*mid相比较;当临时栈顶元素优先级大于等于输入符号的优先级时,出栈;否则符号入栈(已经弹出一个,记得把弹出的元素也入栈)
            pop(&S,&e);
            if('+'==*mid || '-'==*mid){
                if(e=='('){
                    push(&S,'(');
                    push(&S,*(mid++));
                    continue;
                }else{
                    *(final++)=e;
                    push(&S,*(mid++));
                    continue;
                }
            }else if('*'==*mid || '/'==*mid){
                if('*'==e || '/'==e){
                    *(final++)=e;
                    push(&S,*(mid++));
                    continue;
                }else{
                    push(&S,e);
                    push(&S,*(mid++));
                    continue;
                }
            }

        }else{
            printf("输入的字符不合法!%c\n",*mid);
            return ERROR;

        }
    }
    //当待转换的字符已经结束时,符号栈至少还有一个元素(中缀表达式的特点:数字结尾;后缀表达式以符号结尾);将栈中的元素依次出栈
    while(S.top!=-1){
        pop(&S,&e);
        *(final++)=e;
    }
    //字符串的结束符!
    *final='\0';
}

int main()
{
    /*
    Stack S;
    int i,n,e;
    if(OK!=InitStack(&S)){
        printf("初始化失败!");
        return ERROR;
    }
    printf("输入初始化栈的长度n=");
    scanf("%d",&n);
    if(OK==CreateStack(&S,n)){
            for(i=0;i<=S.top;i++){
                printf("%d\t",S.data[i]);
            }

    }
    printf("\n输入想要插入栈的值");
    while(1==scanf("%d",&e)){
        if(ERROR==push(&S,e)){
            break;
        }else{
            for(i=0;i<=S.top;i++)
                 printf("%d\t",S.data[i]);
        }
    }
    printf("\n接下来测试出栈!栈中的元素依次出栈\n");
    while(OK==pop(&S,&e)){
        getchar();
        printf("%d\t",e);
    }
    */
    char data[]="3+(5*6-7/1*7)*9";
    char final[]="";
    MidToFinal(data,final);
    printf("%s\n",final);

    return 0;
}


  • 9
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
中缀表达式后缀表达式可以使用实现,具体步骤如下: 1. 初始化两个:一个用于存储操作符,一个用于存储后缀表达式。 2. 从左到右扫描中缀表达式,如果当前扫描到的是操作数,将其加入后缀表达式。 3. 如果当前扫描到的是操作符,则与操作符顶的元素进行比较,如果操作符顶的优先级大于等于当前操作符,则将操作符顶元素弹出并加入后缀表达式,直到操作符顶的优先级小于当前操作符或者操作符为空,然后将当前操作符压入操作符。 4. 如果当前扫描到的是左括号,直接将其压入操作符。 5. 如果当前扫描到的是右括号,不断地将操作符顶的元素弹出并加入后缀表达式,直到遇到左括号为止,然后将左括号从操作符中弹出。 6. 扫描完中缀表达式后,将操作符中的所有元素依次弹出并加入后缀表达式。 下面是一个使用C语言实现中缀表达式后缀表达式的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_SIZE 100 // 定义操作符后缀表达式 char op_stack[MAX_SIZE]; int op_top = -1; char postfix_stack[MAX_SIZE]; int postfix_top = -1; // 判断是否为操作符 int is_operator(char c) { return (c == '+' || c == '-' || c == '*' || c == '/'); } // 获取操作符优先级 int precedence(char c) { if (c == '+' || c == '-') { return 1; } else if (c == '*' || c == '/') { return 2; } else { return 0; } } // 将中缀表达式换为后缀表达式 void infix_to_postfix(char *infix) { int i = 0; while (infix[i] != '\0') { if (infix[i] == ' ') { // 忽略空格 i++; continue; } if (is_operator(infix[i])) { while (op_top >= 0 && precedence(op_stack[op_top]) >= precedence(infix[i])) { postfix_stack[++postfix_top] = op_stack[op_top--]; } op_stack[++op_top] = infix[i]; } else if (infix[i] == '(') { op_stack[++op_top] = infix[i]; } else if (infix[i] == ')') { while (op_stack[op_top] != '(') { postfix_stack[++postfix_top] = op_stack[op_top--]; } op_top--; // 弹出左括号 } else { // 操作数直接输出到后缀表达式 postfix_stack[++postfix_top] = infix[i]; } i++; } while (op_top >= 0) { postfix_stack[++postfix_top] = op_stack[op_top--]; } } int main() { char infix[MAX_SIZE]; printf("请输入中缀表达式:"); fgets(infix, MAX_SIZE, stdin); infix_to_postfix(infix); printf("后缀表达式为:%s\n", postfix_stack); return 0; } ``` 代码中使用了两个,一个用于存储操作符,一个用于存储后缀表达式。`is_operator`函数用于判断字符是否为操作符,`precedence`函数用于获取操作符的优先级。`infix_to_postfix`函数用于将中缀表达式换为后缀表达式,具体实现参照上面的步骤。最后调用`infix_to_postfix`函数并输出结果即可。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值