一、基本概念
中缀表达式如1*2+(2-1), 其运算符一般出现在操作数之间, 因此称为中缀表达式,也就是大家编程中写的表达式。
将中缀表达式进行改写,变为后缀表达式 如上面的表达式1*2+(2-1), 就变为12*21-+;后缀表达式中不含有括号, 且后缀表达式的操作数和中缀表达式的操作数排列次序完全相同, 只是运算符的次序发生了改变。
如果你想做一个计算器,那么首先需要用户输入一串表达式,该表达式一般是中缀表达式,我们可以讲表达式记录下来,可是如何才能计算其值呢?需要两步,第一步就是将其装换为后缀表达式,第二步是计算值。今天来学习如何转换为后缀表达式。
二、问题描述
请编写程序将一个中缀表达式转换为后缀表达式。
输入:仅一行,是一个中缀表达式。输入的符号中只有这些基本符号“0123456789+-*/()”,并且不会出现形如2*-3的格式,所有数字都是个位数,“/”表示整除运算。
输出:仅一行,是转换后的后缀表达式。数字之间、运算符之间、数字和运算符之间都用一个空格隔开(参见样例)。
样例:in:8-(3+2*6)/5+4 out:8 3 2 6 * + 5 / - 4 +
三、算法分析
转换后的后缀表达式的操作数之间的顺序不会改变,但操作符的顺序会改变,我们用数组ans[]来保存转换后的结果。
遍历中缀表达式,当遇到操作数时,直接添加到ans后面;当遇到操作符时,则需要分别来处理如下(这里需要用到栈):
1.如果是‘(’,则直接压入栈;
2.如果是‘)’,则依次从栈中弹出操作符到ans的后面,直到遇到‘(’或者栈为空 {如果中缀表达式正确,则一定会碰到‘(’}
3.如果是其它操作符,若栈为空,则将其压入栈;若栈不空,且栈顶的操作符优先级大于或等于当前操作符的优先级,则将其弹出并添加到ans的后面,并继续与新的栈顶进行比较,直到栈为空或栈顶的优先级小于当前操作符的优先级,此时再将当前操作符入栈;若栈不空,且栈顶的操作符优先级小于当前操作符优先级,直接入栈。
4.遍历结束后,若栈中还有操作符,依次弹出并添加到ans即可。
stack_yutao.h
#include <stdio.h>
#include <stdlib.h>
typedef char elemtype;
typedef struct
{
elemtype *array;
int size;
int top;
}stack;
/*
function:initial the stack with the size
input:stack *s, int size
output:void
*/
void initStack(stack *s, int size)
{
s->size = size;
s->top = -1;
s->array = (elemtype *)malloc(sizeof(elemtype) * s->size);
}
/*
function:check whether the stack is full
input:stack *s
output: 1--the stack is full; 0--the stack is not full
*/
int is_stack_full(stack *s)
{
return (s->size - 1) <= s->top;
}
/*
function:check whether the stack is empty
input:stack *s
output: 1--the stack is empty; 0--the stack is not empty
*/
int is_stack_empty(stack *s)
{
return s->top < 0;
}
/*
function:push data to the stack,if the stack is full, it will stop
input:stack *s, int data
output:void
*/
void push(stack *s, elemtype data)
{
if (is_stack_full(s))
{
printf("The stack is also full !\n");
exit(1);
}else
{
s->top ++;
s->array[s->top] = data;
}
}
/*
function:pop from the stack and no data will be return ,if the stack is empty, it will stop
input:stac *s
output:void
*/
void pop(stack *s)
{
if(is_stack_empty(s))
{
printf("The stack is also empty !\n");
system("pause");
exit(1);
}else
{
s->top --;
}
}
/*
function:get the top element of the stack for data, if the stack is empty, it will stop
input:stack *s, int &data
output:void
*/
void get_top(stack *s, elemtype *data)
{
if(is_stack_empty(s))
{
printf("The stack is also empty !\n");
system("pause");
exit(1);
}else
{
*data = s->array[s->top];
}
}
/*
fucntion:destory the stack
input:stack *s
output:void
*/
void destory_stack(stack *s)
{
free(s->array);
}
#include <stdio.h>
#include <stdlib.h>
#include "stack_yutao.h"
int compare(elemtype a, elemtype b);
void infix_to_postfix(const char infix_array[],int n, char postfix_array[]);
void display_array(elemtype array[], int n);
void infix_to_postfix(const char infix_array[],int n, char postfix_array[])
{
int i;
int index = 0;
elemtype top_elem;
elemtype stack_size = 5;
stack char_stack;
stack *s = &char_stack;
initStack(s,stack_size);
for(i = 0; i < n; i ++)
{
if(48 <= infix_array[i] && infix_array[i] <= 57)//若为0-9的数字,则直接将其复制到postfix,并continue到下一次循环
{
postfix_array[index ++] = infix_array[i];
continue;
}
switch(infix_array[i])
{
case '(':
if(!is_stack_full(s))
{
push(s,infix_array[i]);
}
break;
case ')':
get_top(s,&top_elem);
if(!is_stack_empty && top_elem != '(')
{
postfix_array[index ++] = top_elem;
pop(s);
get_top(s,&top_elem);
}
if(top_elem == '(')
{
pop(s);
}
break;
case '+':
case '-':
case '*':
case '/':
if(is_stack_empty(s))
{
push(s,infix_array[i]);
}else
{
get_top(s,&top_elem);
while(compare(top_elem,infix_array[i]) >= 0 && top_elem != '(')
{
postfix_array[index ++] = top_elem;
pop(s);
if(is_stack_empty(s))
{
break;
}else
{
get_top(s,&top_elem);
}
}
push(s,infix_array[i]);
}
break;
default:
printf("There is wrong char in your infix_array !\n");
break;
}
}
while(!is_stack_empty(s))
{
get_top(s,&top_elem);
postfix_array[index ++] = top_elem;
pop(s);
}
postfix_array[index] = '\0';
}
int compare(elemtype a, elemtype b)
{
if(a == '+' || a == '-')
{
if(b == '+' || b == '-')
{
return 0;
}else
{
return -1;
}
}
if(a == '*' || a == '/')
{
if(b == '+' || b == '-')
{
return 1;
}
if(b == '*' || b == '/')
{
return 0;
}
if(b == '(')
{
return -1;
}
}
if(a == '(')
{
return 1;
}
}
int main()
{elemtype infix_array[] = "8-(3+2*6)/5+4";
int n = 13;
elemtype postfix_array[13];
infix_to_postfix(infix_array,n,postfix_array);
display_array(infix_array,n);
display_array(postfix_array,n);
system("pause");
return 0;
}
void display_array(elemtype array[], int n)
{
int i;
for (i = 0; i < n; i ++)
{
printf("%c ",array[i]);
}
printf("\n");
}