中缀转后缀表达式并求值

中缀转后缀表达式

最近学数据结构和算法,老师让我们写算法把任意的中缀表达式(有括号,有加减乘除,无负号)转后缀,并计算它,于是贴出来一篇小文记录一下啦

  • 对于一个寻常的数学算式,把它用计算机的思维解出来,就要首先把它化成后缀表达式,如果有了建树思想的话,对中缀转后缀或许更加能理解,把后缀转化成树也是很轻松的事情。
  • 这里我用了两个栈,一个是放表达式,一个是放表达式里各个数值、方便计算,二话不多说,贴代码
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define maxSize 90
#define ELETYPE char
//
typedef struct Node {
	ELETYPE data;                   
	struct Node *next;    		
}lNode,*Linklist;

typedef struct nNode {
	int data;                   
	struct nNode *next;    		
}nlNode,*nLinklist;

nLinklist ninitStack(nLinklist top){
	top=NULL;
	return top;
}
nLinklist npush(nLinklist top,int data)
	{
		nLinklist node;
		node=(nLinklist)malloc(sizeof(nlNode));
		if(!node){
			return top;
		}
		else{
			node->data=data;
			node->next=top;
			top=node;		
			return top;
		}
	}
nLinklist npop(nLinklist top,int *data)
{
	if(top==NULL)
	return NULL;
	else
	{
	 *data=top->data;
	nLinklist node=top;
	top=top->next;
	free(node);
	return top;
}
}
int sum(char tem[],int sizearr[],int numarr[]){
	nLinklist top=malloc(sizeof(nlNode));
	 top=ninitStack(top);
	 int i=0,count=0,num1=0,num2=0;
	while(i!=maxSize)
	{
		if(tem[i]>='0'&&tem[i]<='9')
		{
			top=npush(top,numarr[count]);
			i+=sizearr[count];
			count++;
			continue;
		}
			
	else if(tem[i]=='+')
		{	
		top=npop(top,&num1);
		top=npop(top,&num2);
		top=npush(top,num2+num1);
		}
	else if(tem[i]=='-')
	{	
		top=npop(top,&num1);
		top=npop(top,&num2);
		top=npush(top,num2-num1);
		}
	else if(tem[i]=='*')
	{	
		top=npop(top,&num1);
		top=npop(top,&num2);
		top=npush(top,num2*num1);
		}
	else if(tem[i]=='/')
	{	
		top=npop(top,&num1);
		top=npop(top,&num2);
		top=npush(top,num2/num1);
	}
	i++;	
	}
	
	top=npop(top,&num1);
	printf("%d\n",num1);
	return 1;
} 
//上边是最后计算算式用到的栈,下面开始转后缀
ELETYPE getData(Linklist top);
Linklist push(Linklist top,ELETYPE data);
Linklist pop(Linklist top,ELETYPE *data);
int isEmpty(Linklist top);
 Linklist initStack(Linklist top);

Linklist initStack(Linklist top){
	top=NULL;
	return top;
}
ELETYPE getData(Linklist top){
	if(top==NULL)
	return 0;
	else
	return top->data;
}
Linklist push(Linklist top,ELETYPE data)
	{
		Linklist node;
		node=(Linklist)malloc(sizeof(lNode));
		if(!node){
			return top;
		}
		else{
			node->data=data;
			node->next=top;
			top=node;		
			return top;
		}
	}
Linklist pop(Linklist top,ELETYPE *data)
{
	if(top==NULL)
	return NULL;
	else
	{
	 *data=top->data;
	Linklist node=top;
	top=top->next;
	free(node);
	return top;
}
}


int isEmpty(Linklist top){
	if(top==NULL)
	return 1;
	else 
	return 0;
	
}
int compareCharacter(char c1,char c2){
	int n1,n2;
	 switch(c1)
    {
    case '(':   n1= 0;break;  
    case '+':
    case '-':    n1= 1;break;
    case '*':
    case '%':
    case '/':   n1=2;break;
    default :   n1=-100;break;
    }
	switch(c2)
    {
    case '(':   n2= 0;break;  
    case '+':
    case '-':    n2= 1;break;
    case '*':
    case '%':
    case '/':   n2=2;break;
    default :   n2=-1;break;
    }
	if(n1>=n2)
	return 1;
	else
	return 0;
}
Linklist reverse_polish(Linklist top,ELETYPE arr[],int sizearr[],int numarr[]){
	char tem[maxSize]={0};
	int i=0,count=0;
	while(arr[i]!='#')
	{
		if(arr[i]>='0'&&arr[i]<='9')
		{
			tem[count++]=arr[i++];
	
			continue;
		}
		
		if(arr[i]=='(')
		{
		top=push(top,arr[i]);
		i++;
	
		continue;
		}
		
		if(arr[i]=='+'||arr[i]=='-'||arr[i]=='*'||arr[i]=='/'||arr[i]=='%')
		{
			if(!isEmpty(top)&&compareCharacter(getData(top),arr[i]))
			{
			while(!isEmpty(top)&&compareCharacter(getData(top),arr[i]))
			{if(getData(top)!='(')
			top=pop(top,&tem[count]);
		
			count++;				
			}
			} 		
			else {
				top=push(top,arr[i]);
					i++;			
					continue;
			}
			top=push(top,arr[i]);
				i++;
		}
		if(arr[i]==')')
		{
			while(getData(top)!='(')
			top=pop(top,&tem[count++]);
				
				char n=0;
			top=pop(top,&n);
			
			i++;
		}
			
	}
	while(!isEmpty(top))
	{
		top=pop(top,&tem[count++]);
	}
	int count2=0;
	int count3=0;
	int count4=0;
	//下边一部分就是把后缀表达式的各个数和运算符分割开来,方便阅读
	while(tem[count2]!=0)
	{
	printf("%c",tem[count2]);
		count2++;
		if(tem[count2-1]>='0'&&tem[count2-1]<='9')
			count3++; 
		
		if(tem[count2-1]=='+'||tem[count2-1]=='-'||tem[count2-1]=='*'||tem[count2-1]=='/'&&tem[count2]!=0)
		printf(" ");
		else if(count3==sizearr[count4]&&tem[count2-1]>='0'&&tem[count2-1]<='9')
		{
		printf(" ");
		count3=0;
		count4++;
		}
	
	}
	tem[count]='\0';
	printf("\n");
	sum(tem,sizearr,numarr);
	return 1;
	
}
//把一个表达式分解成各个数,并计算各个数的位数,为后面输出表达式及计算表达式的值做铺垫
int *arrAddition(char arr[],int numarr[],int sizearr[]){
	int i=0,tem=0,count=0,tem2=0,boole=0;
	
	while(arr[i]!='#')
	{
		while(arr[i]>='0'&&arr[i]<='9'){
			tem++;			
			i++;			
		}
		for(tem2=tem;tem2>0;tem2--)
		{
			numarr[count]+=(arr[i-tem2]-48)*pow(10,tem2-1);
			sizearr[count]++;
				boole=1;	
		}
		
		if(boole==1)	
		{
			count++;
			boole=0;
		}
		if(arr[i]=='#')
		return 0;
		i++;
		tem=0;
		
	}
		return 1;

} 
	
int main(){
	
	char arr[maxSize]={0};
	
	
	while((scanf("%s",arr))!=EOF) 
	{
	Linklist top=malloc(sizeof(lNode));
	int numarr[maxSize]={0},sizearr[maxSize]={0};
	 top=initStack(top);
	 arrAddition(arr,numarr,sizearr);
     reverse_polish(top,arr,sizearr,numarr);
	}
	return 1;	 
}










测试是否正确(表达式最后以#做结尾)
实测是否正确

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值