精华内容
下载资源
问答
  • C++程序,将后缀表达式用栈转换为前缀表达式
  • 仿照后缀表达式的计算过程,把用字符数组来保存计算结果。 【代码】 #include <stdio.h> #include <stdlib.h> #include <string.h> #define maxSize 100 typedef struct BTNode { char data;...

    【原理】

    仿照后缀表达式的计算过程,把用字符数组来保存计算结果。

    【代码】

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define maxSize 100
    
    typedef struct BTNode
    {
    	char data;
    	struct BTNode* lchild, *rchild;
    }BTNode;
    
    
    char* comtoin(char* exp)
    {
    	char* stack[maxSize];
    	char* a,*b;
    	int top = -1;
    
    	int i = 0,j;
    	char* s;
    	char op;
    	while (exp[i] != '\0')
    	{
    		if (exp[i] >= '0' && exp[i] <= '9')
    		{
    			s = (char*)malloc(sizeof(char));
    			j = 0;
    			s[j++] = exp[i];
    			s[j] = '\0';
    			stack[++top] = s;
    		}
    		else
    		{
    			b = stack[top--];//取第二个操作数
    			a = stack[top--];//取第一个操作数
    			
    			s = (char*)malloc(sizeof(char));
    			j = 0;
    			s[j++] = exp[i];//取操作符
    			s[j] = '\0';
    
    			//连接表达式
    			strcat(a, s);
    			strcat(a, b);
    
    			stack[++top] = a;//入栈
    		}
    		i++;
    	}
    
    	return stack[top];
    }
    
    
    //后序和中序确定一棵二叉树
    BTNode* CreateBT(char post[], char in[], int l1, int r1, int l2, int r2)
    {
    	if (l1 > r1)
    		return NULL;
    	BTNode* bt = (BTNode*)malloc(sizeof(BTNode));
    	bt->data = post[r1];
    
    	//在中序序列中查找根结点的位置
    	int i;
    	for (i = l2; i <= r2; ++i)
    		if (in[i] == post[r1])
    			break;
    	//确定左右子树
    	bt->lchild = CreateBT(post, in, l1, l1 + i - l2 - 1, l2, i - 1);
    	bt->rchild = CreateBT(post, in, l1 + i - l2, r1 - 1, i + 1, r2);
    
    	return bt;
    }
    
    //非递归先序遍历,获取前缀表达式
    char* preorder(BTNode* root,int n)
    {
    	char* s = (char*)malloc(sizeof(char)*(n + 1));
    	int i = 0;
    
    	if (root != NULL)
    	{
    		BTNode* stack[maxSize];
    		int top = -1;
    		BTNode* p = NULL;
    
    		//根结点入栈
    		stack[++top] = root;
    
    		while (top != -1)
    		{
    			p = stack[top--];
    
    			//存储出栈元素
    			s[i++] = p->data;
    
    			//先将p的右子树入栈,再将其左子树入栈
    			if (p->rchild != NULL)
    				stack[++top] = p->rchild;
    			if (p->lchild != NULL)
    				stack[++top] = p->lchild;
    		}
    	}
    
    	s[i] = '\0';
    	return s;
    }
    
    int main()
    {
    	char post[maxSize] = "123*+45/-";
    	puts(post);
    	
    	//后缀转中缀
    	char* in = comtoin(post);
    	puts(in);
    
    	//构建二叉树
    	int l1 = 0, r1 = strlen(post) - 1;
    	int l2 = 0, r2 = strlen(in) - 1;
    	BTNode* root = CreateBT(post, in, l1,r1, l2, r2);
    
    	//形成前缀表达式
    	char* s = preorder(root, r1 - l1 + 1);
    
    	puts(s);
    
    	system("pause");
    
    	return 0;
    }
    

     

    展开全文
  • 栈实现后缀表达式转前缀表达式

    千次阅读 2018-01-14 15:42:23
    先看下面的图片,这是后缀表达式32/6*3-3+转前缀的过程 对于表达式:32/6*3-3+ 其前缀式为:+-*/32633 操作数的顺序不会改变,变的是运算符的顺序,并且在后缀式中,运算顺序从左往...

    先看下面的图片,这是后缀表达式32/6*3-3+转前缀的过程








    对于表达式:32/6*3-3+

    其前缀式为:+-*/32633

    操作数的顺序不会改变,变的是运算符的顺序,并且在后缀式中,运算顺序从左往右,在前缀式中,正好反过来(但是运算符不一定正好反过来),这跟我们自己运算这两个表达式的顺序是一样的。转换的关键,就在如何找准操作符的两个操作数。

    观察后缀表达式,对于32,越靠右边的操作数对32的运算迫切程度降低,总是要等到前面的运算符运算完才可以对32进行运算,由此想到栈结构来存储运算符。

    总的思路如下:

    指针从最后边扫描起,遇到操作符则存入栈中并且从表达式中删除该操作符,同时标记其匹配的操作数为0,如果遇到操作数,则应该对栈顶的操作符的配对操作数加一,当新来一个操作符时,对前面操作符的操作数配对期望降低,转而对新来的操作符先行配对操作数。当一个操作符成功配对两个操作数时,其配对期望程度为0,从栈中取出,插入到其两个操作数的前面,整体作为此时栈顶操作符新的操作数,并记录到栈顶操作符的操作数匹配数中。如果此时该栈顶操作符的操作数匹配恰好又为2,则再次取出,插入到其两个操作数前面,迭代此过程,直到栈顶操作符的操作数匹配数不足2或者栈空为止。


    因为是如上的考虑,所以表达式存储采用链表,提高插入删除效率。

    同时栈的data域要包含两个成员,其一为操作符,其二为该操作符匹配的操作数的数目。


    下面是代码:

    Status Convert(Expression *exp)
    {//算法将后缀式exp转换为前缀式,如果后缀式不合法,则返回ERROR	
    	SeqStack S;
    	InitStack(&S);
    
    	Revers(exp);//revers the expression
    	Ptr p = exp;
    	while (p->next!=NULL)//expression is still not over
    	{
    		if (Is_optr(p->next->ch))//is it an operator?
    		{
    			StackElem optr;
    			optr.optr = p->next->ch;
    			optr.its_oprd = 0;
    			Push(&S, optr);
    			Delet(exp, p);//delete the operator from expression
    		}
    		else
    		{
    			if (IsEmpty(&S))
    				return ERROR;//expression is illegal!
    			else
    			{
    				while (!IsEmpty(&S))
    				{
    					StackElem optr;
    					GetTop(&S, &optr);
    					Pop(&S);
    					if (++optr.its_oprd < 2)
    					{
    						Push(&S, optr);
    						break;
    					}
    					else
    					{
    						p = p->next;
    						Insert(exp, p, optr.optr);
    					}
    				}
    				p = p->next;
    			}
    		}
    	}
    	if (!IsEmpty(&S))
    		return ERROR;//expression is illegal!
    	
    	Revers(exp);
    	return OK;
    }
    算法包含对后缀正确的判断,错误的后缀式(不算怪异字符,如不应该出现的‘】’‘&’等等)有两种情况,一种是取栈中元素时栈为空,说明此时后缀式存在非法的操作数过多的子表达式,第二种是表达式转换完栈不空,说明后缀式操作符过多。


    如果你想运行上面的代码,你需要完整的源代码,如下:

    #include "stdafx.h"
    #include<stdio.h>
    #include<iostream>
    #include<malloc.h>
    #define Status int
    #define OVERFLOW -1
    #define ERROR 0
    #define OK 1
    #define STACK_INI_SIZE 10//顺序栈初始化长度
    #define STACK_INC_SIZE 2//顺序栈单次扩充长度
    
    typedef struct StackElem
    {
    	char optr;
    	int  its_oprd;//属于optr操作数出现的次数
    }StackElem;//栈的元素类型
    typedef struct SeqStack
    {
    	StackElem  *base;
    	int        top;
    	int        capacity;//容量
    }SeqStack;
    typedef struct LinkList
    {
    	char ch;//表达式元素
    	struct LinkList *next;
    }Expression,ENode,*Ptr;
    
    
    /*The major function*/
    Status Convert(Expression *exp);
    bool Is_optr(char ch);
    
    /*Basic operation of SeqStack*/
    //初始化栈
    Status InitStack(SeqStack *S);
    //获取栈顶元素的数据
    Status GetTop(SeqStack *S, StackElem *optr);
    //入栈
    Status Push(SeqStack *S, StackElem optr);
    //出栈
    Status Pop(SeqStack *S);
    //栈判空
    bool IsEmpty(SeqStack *S);
    //扩充栈空间
    Status Extern(SeqStack *S);
    
    /*Basic operation of Expression*/
    //初始化表达式
    Status InitExp(Expression **exp);
    //构建表达式
    Status Push_back(Expression *exp, char ch);
    //插入节点
    Status Insert(Expression *exp,Ptr p,char ch);
    //删除节点
    Status Delet(Expression *exp, Ptr p);
    //逆置表达式
    Status Revers(Expression *exp);
    //输出表达式
    Status Show(Expression *exp);
    
    
    
    int main()
    {
    	using namespace std;
    
    	ENode *exp;
    	InitExp(&exp);//初始化空表达式
    
    	cout << "Input a postfix expression(press @ to end input),thanks\n";
    	char ch;
    	while (cin >> ch, ch != '@')
    	{
    		Push_back(exp, ch);
    	}//expression like this  36*32/-
    
    	if (Convert(exp))
    		Show(exp);
    	else
    		cout << "Your expression is illegal\n";
    
    	return 0;
    }
    
    Status Convert(Expression *exp)
    {//算法将后缀式exp转换为前缀式,如果后缀式不合法,则返回ERROR	
    	SeqStack S;
    	InitStack(&S);
    
    	Revers(exp);//revers the expression
    	Ptr p = exp;
    	while (p->next!=NULL)//expression is still not over
    	{
    		if (Is_optr(p->next->ch))//is it an operator?
    		{
    			StackElem optr;
    			optr.optr = p->next->ch;
    			optr.its_oprd = 0;
    			Push(&S, optr);
    			Delet(exp, p);//delete the operator from expression
    		}
    		else
    		{
    			if (IsEmpty(&S))
    				return ERROR;//expression is illegal!
    			else
    			{
    				while (!IsEmpty(&S))
    				{
    					StackElem optr;
    					GetTop(&S, &optr);
    					Pop(&S);
    					if (++optr.its_oprd < 2)
    					{
    						Push(&S, optr);
    						break;
    					}
    					else
    					{
    						p = p->next;
    						Insert(exp, p, optr.optr);
    					}
    				}
    				p = p->next;
    			}
    		}
    	}
    	if (!IsEmpty(&S))
    		return ERROR;//expression is illegal!
    	
    	Revers(exp);
    	return OK;
    }
    
    bool Is_optr(char ch)
    {//判断ch是否是运算符
    	return ch == '+' || ch == '-' || ch == '*' || ch == '/';
    }
    
    Status InitStack(SeqStack *S)
    {//初始化栈
    	S->base = (StackElem*)malloc(sizeof(StackElem)*STACK_INI_SIZE);
    	if (!S->base)
    		return OVERFLOW;
    
    	S->capacity = STACK_INI_SIZE;
    	S->top = 0;
    	return OK;
    }
    
    
    Status GetTop(SeqStack *S, StackElem *optr)
    {//获取栈顶元素数据
    	if (IsEmpty(S))
    		return ERROR;
    
    	optr->optr = S->base[S->top - 1].optr;
    	optr->its_oprd = S->base[S->top - 1].its_oprd;
    	return OK;
    }
    
    
    Status Push(SeqStack *S, StackElem optr)
    {
    	if (S->top == S->capacity && !Extern(S))
    		return OVERFLOW;
    
    	S->base[S->top].its_oprd = optr.its_oprd;
    	S->base[S->top].optr = optr.optr;
    	S->top++;
    	return OK;
    }
    
    Status Pop(SeqStack *S)
    {
    	if (IsEmpty(S))
    		return ERROR;
    
    	S->top--;
    	return OK;
    }
    
    
    bool IsEmpty(SeqStack *S)
    {
    	return S->top == 0;
    }
    
    
    Status Extern(SeqStack *S)
    {
    	StackElem *newbase;
    	newbase = (StackElem*)realloc(S->base, (S->capacity + STACK_INC_SIZE) * sizeof(StackElem));
    	if (!newbase)
    		return OVERFLOW;
    
    	S->base = newbase;
    	S->capacity += STACK_INC_SIZE;
    	return OK;
    }
    
    Status InitExp(Expression **exp)
    {//初始化空表达式
    	*exp = (ENode*)malloc(sizeof(ENode));
    	if (!(*exp))
    		return OVERFLOW;
    
    	(*exp)->next = NULL;
    	return OK;
    }
    
    Status Push_back(Expression *exp, char ch)
    {//尾部插入
    	ENode *p = exp, *s;
    
    	while (p->next != NULL)
    	{
    		p = p->next;
    	}
    	s = (ENode*)malloc(sizeof(ENode));
    	if (!s)
    		return OVERFLOW;
    
    	s->next = NULL;
    	s->ch = ch;
    	s->next = p->next;
    	p->next = s;
    	return OK;
    }
    
    Status Insert(Expression *exp, Ptr p, char ch)
    {//在指针p的后面插入节点ch
    	ENode *s = (ENode*)malloc(sizeof(ENode));
    	if (!s)
    		return OVERFLOW;
    
    	s->next = NULL;
    	s->ch = ch;
    	s->next = p->next;
    	p->next = s;
    	return OK;
    }
    
    Status Delet(Expression *exp, Ptr p)
    {//删除P后面的节点
    	if (p->next == NULL)
    		return ERROR;
    
    	ENode *q = p->next;
    	p->next = q->next;
    	free(q);
    	return OK;
    }
    
    Status Revers(Expression *exp)
    {//逆置表达式exp
    	if (exp->next == NULL || exp->next->next == NULL)
    		return OK;
    
    	ENode *p, *s;
    	p = exp->next->next;
    	exp->next->next = NULL;
    	s = p;
    	while (p != NULL)
    	{
    		s = s->next;
    		p->next = exp->next;
    		exp->next = p;
    		p = s;
    	}
    	return OK;
    }
    
    Status Show(Expression *exp)
    {//输出表达式
    
    	ENode *p = exp;
    	while (p->next != NULL)
    	{
    		std::cout << p->next->ch << ' ';
    		p = p->next;
    	}
    	return OK;
    }

    不足之处请提出来,希望能帮到你!

    展开全文
  • //表达式中操作数存在一个栈内,运算符存入一个栈内 //top1,top2用于指向两个栈的栈顶 float s1[maxSize];int top1=-1; char s2[maxSize];int top2=-1; while(exp[i]!='\0'){//字符串结尾以'\0' if(exp...
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #define Min 1e-8
    #define maxSize 10 
    int priority(char p){
    	 if(p=='+'||p=='-'){
    		return 0;
    	}else{
    		return 1;
    	}
    } 
    //子表达的计算 
    int calSub(float opand1,char op,float opand2,float &result){
    	//根据操作符进行计算 
    	if(op == '*') result=opand1*opand2;
    	if(op == '+') result=opand1+opand2;
    	if(op == '-') result=opand1-opand2;
    	if(op == '/'){//若是除则需要判断除数为零的情况 
    		if(fabs(opand2)<Min){// 浮点数没有准确的表达,只能用绝对值来表示差不多的范围 
    			return 0;
    		}
    		else{
    			result =opand1/opand2;
    		}
    	} 
    	return 1;
    }
    int calStackTopTwo(float s1[],int &top1,char s2[],int &top2){
    	float a=s1[top1--];//弹出栈顶元素后指针下移 
    	float b=s1[top1--];
    	float result; 
    	char op=s2[top2--];
    	int flag=calSub(b,op,a,result);//进行子表达式的计算 
    	if(flag==0){
    		printf("被除数为零"); 
    		return 0;
    	}
    	s1[++top1]=result;//计算结果存入栈顶 
    	return 1;
    	
    } 
    //计算表达式的函数 
    float getResult(char exp[]){
    	int i=0;//用于指向字符串(中缀表达式)的指针 
    	//声明两个栈,一个float型,一个char型 
    	//表达式中操作数存在一个栈内,运算符存入一个栈内
    	//top1,top2用于指向两个栈的栈顶 
    	float s1[maxSize];int top1=-1; 
    	char s2[maxSize];int top2=-1;
    	
    	while(exp[i]!='\0'){//字符串结尾以'\0' 
    		if(exp[i]>='0'&&exp[i]<='9'){//判断是否是数字,但此处只能判断0-9之间的一位数字 
    			 s1[++top1]=exp[i]-'0';//字符串转换为数字 
    			 ++i;//下一个字符 
    		} 
    		else if(exp[i]=='(') {//如果是左括号的话直接进栈 
    			s2[++top2]='(';
    			i++;
    		}else if(exp[i]=='*'|| //如果是运算符则进行以下判断 
    				 exp[i]=='/'||
    				 exp[i]=='+'||
    				 exp[i]=='-'){
    				 	//如果栈顶为左括号或者栈空,或者当前符号优先级大于栈顶符号优先级则入栈 
    				 	if(s2[top2]=='('||top2==-1||priority(exp[i])>priority(s2[top2])){
    				 		s2[++top2]=exp[i];
    				 		i++;
    					 }else{
    					 	int flag=calStackTopTwo(s1,top1,s2,top2);//当前运算符小于栈顶元素优先级则弹出数据栈的两个 
    						if(flag==0){
    							return 0;
    						}
    					 }                                  //操作数,进行运算后存入栈顶,完毕后i的值不发生 
    				 }                                      //变化 
    		 else if(exp[i]==')'){//如果碰到右括号,则弹出栈内直至左括号的所有运算符 
    		 	while(s2[top2]!='('){//弹出一个运算符都需要进行计算 
    		 		int flag=calStackTopTwo(s1,top1,s2,top2);
    		 		if(flag==0){
    							return 0;
    						}
    		 		
    			 }
    			 --top2;//更新栈顶指针 
    			 i++;
    		 	
    		 }
    	
    	}
    	//当表达式进栈完毕后 
    	//只要符号栈内还有元素就继续进行运算 
    	while(top2!=-1){
    		 	int flag=calStackTopTwo(s1,top1,s2,top2);
    		 	if(flag==0){
    		 		return 0;
    			 } 
    		 }
    	return s1[top1];
    }
    //后缀表达式计算 
    float calPostFix(char exp[]){
    	float s1[maxSize];
    	int top=-1;
    	int i=0;
    	while(exp[i]!='\0'){
    		if(exp[i]>='0'&&exp[i]<='9'){
    			s1[++top]=exp[i]-'0';
    		}else{
    			float a,b,result;
    			a=s1[top--];
    			b=s1[top--];//出栈顶的两个元素 
    			int flag=calSub(a,exp[i],b,result);//子表达式计算结果存入result 
    			if(flag==0){
    				printf("Error");
    				return 0;
    			}
    			s1[++top]=result;//将结果存入栈顶 
    		}
    		i++;
    		 
    	}
    	return s1[top];
    	
    }
    float calPreFix(char exp[],int length){
    	float s1[maxSize];
    	int top=-1;
    	for(int i=length-1;i>=0;--i){
    		if(exp[i] >= '0' && exp[i]<='9'){
    			//printf("%c",exp[i]);
    			s1[++top]=exp[i]-'0';
    		}else
    		{   
    			float a,b,result;
    			a=s1[top--];
    			b=s1[top--];//出栈顶的两个元素 
    		//	printf("%f %f",s1[0],s1[1]);
    			int flag=calSub(a,exp[i],b,result);//子表达式计算结果存入result 
    			if(flag==0){
    				printf("Error");
    				return 0;
    			}
    			s1[++top]=result;//将结果存入栈顶 
    		} 
    	}
    	return s1[top];	
    }
    //中缀式转后缀式 
    //参数top传引用型是为了能够查看栈的最大用量 
    //参数s2[]数组是存储结果表达式 
    void infixtoPostFix(char infix[],char s2[],int &top2){
    	char s1[maxSize];//辅助栈 
    	int i=0,top1=-1; 
    	while(infix[i]!='\0'){
    		
    		if(infix[i]<='9'&&infix[i]>='0'){
    			s2[++top2]=infix[i];
    			i++;
    		}else if(infix[i]=='('){
    			s1[++top1]=infix[i];
    		
    			i++;
    		}else if(infix[i]=='*'||infix[i]=='+'||infix[i]=='-'||infix[i]=='/'){
    			if(top1==-1||s1[top1]=='('||priority(infix[i])>priority(s1[top1])){
    				//中缀转后缀,当前运算符优先级小于等于栈顶运算符优先级则出栈 
    				s1[++top1]=infix[i];
    				i++;
    			}else{
    				s2[++top2]=s1[top1--];
    			}
    		}else if(infix[i]==')'){
    			while(s1[top1]!='('){
    				s2[++top2]=s1[top1--];
    				
    			}
    			--top1;//
    			i++;
    		}
    	} 
    	while(top1!=-1){
    		s2[++top2]=s1[top1--];
    		
    	}
    }
    //中缀式转前缀式
    void infixtoPreFix(char infix[],int length,char s3[],int &top2){
    	char s1[maxSize];//辅助栈 
    	char s2[maxSize];// 
    	int i=length-1,top1=-1; 
    	while(i>=0){
    		if(infix[i]<='9'&&infix[i]>='0'){
    			s2[++top2]=infix[i];
    			i--;
    		}else if(infix[i]==')'){
    			s1[++top1]=infix[i];
    			i--;
    		}else if(infix[i]=='*'||infix[i]=='+'||infix[i]=='-'||infix[i]=='/'){
    			//中缀转前缀,当前运算符优先级小于栈顶运算符优先级则出栈 
    			if(top1==-1||s1[top1]==')'||priority(infix[i]) >= priority(s1[top1])){
    				s1[++top1]=infix[i];
    				i--;
    			}else{
    				s2[++top2]=s1[top1--];
    			}
    		}else if(infix[i]=='('){
    			while(s1[top1]!=')'){
    				s2[++top2]=s1[top1--];		
    			}
    			--top1;
    			i--;
    		}
    	} 
    	while(top1!= -1){
    		s2[++top2]=s1[top1--];	
    	}
    	int v=0;
    	for(int i=top2;i>=0;i--){
    		
    		s3[v++]=s2[i];
    	}
    
    }
    int getlength(char s[]){
    	int length=0;
    	for(int i=0;i<maxSize;i++){
    	   if((s[i]<'9'&&s[i]>'0')||s[i]=='+'||s[i]=='*'||
    	        s[i]=='/'||s[i]=='-'||s[i]=='('||s[i]==')'){
    	   	length++;
    	   }	
    	}
    	return length;
    }
    int main(){
    	char s[maxSize];
    	printf("请输入中缀表达式:\n");
    	scanf("%s",s);//录入字符串 
    	printf("%s=%f\n",s,getResult(s));
    	
    	char result[maxSize];//存放转换后结果 
    	int top1=-1;
    	infixtoPostFix(s,result,top1); 
    	printf("中缀转后缀为:%s\n",result);
    	printf("后缀的结果表达式为:%f\n",calPostFix(result));
    	int top2=-1;
    	char result1[maxSize];//存放转换后结果 
    	
    	infixtoPreFix(s,getlength(s),result1,top2); 
    	printf("中缀转前缀为:%s\n",result1);
    	printf("前缀的结果表达式为:%f\n",calPreFix(result1,getlength(s)));
    	
    }

    代码运行截图:

    其中在转化时需要注意:

    展开全文
  • 中缀表达式转前缀后缀表达式

    如果有实现四则混合运算这种需求,经常会遇到如何将中缀表达式转换为前缀或者后缀表达式的问题,在用代码实现转换时,一种常见的转换方式就是使用栈结构。

    我特意整理了一个程序流程图,按照流程图写出程序就会简单很多,黑线部分就是程序的流程走向

    中缀转前缀和中缀转后缀整体思路是一致的,只需要注意三个地方的区别即可

    1.中缀转前缀是从右往左遍历表达式,中缀转后缀是从左往右遍历表达式;

    2.运算符入栈时,对优先级的比较有所差异(中转前是≥ ;中转后是>),具体看下面的流程图红色加粗部分

    3.由于遍历顺序不同,对左右括号的处理也是相反的

    区分前缀和后缀的遍历顺序,以及运算符入栈的优先级比较有所区别就行。

    前提条件:

    创建两个栈,一个用于存储运算符("+"、"-"、"*"、"/"、"("、")"),命名为sign,一个用于存储操作数,命名为num。

    转换完成后取出结果:

    中缀转前缀:依次从栈顶遍历取出num栈的元素,即是前缀表达式

    中缀转后缀:倒叙从栈底遍历取出num栈的元素,即是后缀表达式

    中缀转前缀流程图如下

    走到最后,将如果sign中还有元素,就将其依次出栈然后入栈num,若没有元素就不管sign了

    最后num栈依次出栈的就是所求前缀表达式

    中缀转后缀流程图如下

    走到最后,将如果sign中还有元素,就将其依次出栈然后入栈num,若没有元素就不管sign了

    最后num栈逆序出栈的就是所求前缀表达式

    具体代码实现如下,我只是通过流程图实现了代码,还没有对其做优化

    计算器类Calculator

    import java.util.*;
    
    /**
    *利用前缀、后缀表达式实现计算器计算个位数的四则混合运算
    */
    public class Calculator {
        public static final String PRE = "^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$";//数字校验正则表达式
        /**
         * 传入表达式,计算并返回结果
         * 返回的float类型只提供 -2^31 ~ 2^31-1范围内的运算
         * @param expre 传入的表达式
         * @param calcWay 计算方式:前缀后者后缀
         * @return 计算结果
         */
        public String calculation(String expre,String calcWay){
            char[] exp ;
            Stack<Float> calcStack = new Stack();
            float re = 0;
            if (calcWay.equals("Prefix") || calcWay == "Prefix") {
                exp = convertToPrefix(expre);
                float a,b;
                //逆序遍历,遇到数字入栈,遇到符号取出栈顶两个元素计算并将结果再次入栈
                for (int i = exp.length-1; i >=0; i--) {
                    if(exp[i] == '+' || exp[i] == '-' || exp[i] == '*' || exp[i] == '/'){
                        //取出栈顶两个元素并计算
                        a = calcStack.pop();
                        b = calcStack.pop();
                        switch (exp[i]){
                            //注意运算时,大数在前,小数在后,不然减法和乘法会计算错误
                            case '+':calcStack.push(a+b);break;
                            case '-':calcStack.push(a-b);break;
                            case '*':calcStack.push(a*b);break;
                            case '/':calcStack.push(a/b);break;
                        }
                    }else{
                        calcStack.push((float) exp[i] - '0');
                    }
                }
                re = calcStack.peek();//栈中最后一个元素即为计算结果
                System.out.println("前缀表达式为"+String.valueOf(exp));
            }
            else if(calcWay.equals("Suffix") || calcWay == "Suffix"){
                exp = convertToSuffix(expre);
                System.out.println("后缀表达式为"+String.valueOf(exp));
    
                float a,b;
                for (int i = 0; i < exp.length; i++) {
                    if(exp[i] == '+' || exp[i] == '-' || exp[i] == '*' || exp[i] == '/'){
                        //取出栈顶两个元素并计算
                        a = calcStack.pop();
                        b = calcStack.pop();
                        switch (exp[i]){
                            //注意运算时,大数在前,小数在后,不然减法和乘法会计算错误
                            case '+':calcStack.push(b+a);break;
                            case '-':calcStack.push(b-a);break;
                            case '*':calcStack.push(b*a);break;
                            case '/':calcStack.push(b/a);break;
                        }
                    }else{
                        calcStack.push((float) exp[i] - '0');
                    }
                }
                re = calcStack.peek();//栈中最后一个元素即为计算结果
            }
            else {
                throw new RuntimeException("计算方式只能为'Prefix'或者'Suffix'");
            }
    
            //计算完成后,若为正数,就去掉float后面的小数点和0
            String result = (Math.round(re)-re==0) ? String.valueOf((long)re) : String.valueOf(re);
            return result;
        }
    
        /**
         * 转换为前缀表达式
         * @param expre
         * @return
         */
        public char[] convertToPrefix(String expre){
            char[] preFix = expre.toCharArray();
            Stack<Character> sign = new Stack<>();
            Stack<Character> num = new Stack<>();
    
            for(int i = preFix.length-1;i>=0;i--){//从右到左遍历表达式
                if(preFix[i] == ')'){
                    sign.push(preFix[i]);
                }
                else if(preFix[i] == '('){
                    if(sign.peek() == ')'){
                        sign.pop();//弹出'(' 丢弃
                    }else{
                        //遍历sign栈,并将其中的元素弹出压栈到num栈,直到找到左括号就弹出并结束
                        while (sign.size()>0){
                            if(sign.peek() == ')') {
                                sign.pop();//直到栈顶元素为 ')'结束并丢弃括号
                                break;
                            }
                            num.push(sign.pop());
                        }
                    }
                }
                else if(preFix[i] == '+' || preFix[i] == '-' || preFix[i] == '*' || preFix[i] == '/'){
                    if(sign.empty() || sign.peek() == ')'){//为空或顶部元素为')'就直接压栈
                        sign.push(preFix[i]);
                    }
                    else{
                        if(isHighOrEqualThan(preFix[i],sign.peek())){//当前的运算符比栈顶元素优先级高
                            sign.push(preFix[i]);
                        }
                        else{
                            while (true){
                                //遍历sign栈,将栈顶元素取出并压入num栈
                                // 直到遇到')'或者sign栈空 又或者找到一个元素优先级比当前元素高
                                if(sign.empty() || sign.peek() == ')' || isHighOrEqualThan(preFix[i],sign.peek())) {
                                    sign.push(preFix[i]);
                                    break;
                                }
                                num.push(sign.pop());
                            }
                        }
                    }
                }
                else if(String.valueOf(preFix[i]).matches(PRE)){  //正则验证是否为是数字,直接入栈
                    num.push(preFix[i]);
                }
                else{
                    throw new RuntimeException(preFix[i]+"不是数字和运算符,请检查输入的算式是否正确");
                }
            }
            //遍历完成后,将sign剩余的所有符号依次出栈push到num栈中
            while (sign.size()>0) num.push(sign.pop());
    
            char[] result = new char[num.size()];
            //逆序获取num栈并保存到结果数组
            for(int forntIndex = 0;num.size()>0;forntIndex++){
                result[forntIndex] = num.pop();
            }
            return result;
        }
    
        /**
         * 转换为后缀表达式
         * 转换流程图参考:https://blog.csdn.net/c_o_d_e_/article/details/108774118
         * @param expre
         * @return
         */
        public char[] convertToSuffix(String expre){
            char[] suffix = expre.toCharArray();
            Stack<Character> sign = new Stack<>();
            Stack<Character> num = new Stack<>();
    
            for(int i = 0;i<suffix.length;i++){//从左到右遍历表达式
                if(suffix[i] == '('){
                    sign.push(suffix[i]);
                }
                else if(suffix[i] == ')'){
                    if(sign.peek() == '('){
                        sign.pop();//弹出'(' 丢弃
                    }else{
                        //遍历sign栈,并将其中的元素弹出压栈到num栈,直到找到左括号就弹出并结束
                        while (sign.size()>0){
                            if(sign.peek() == '(') {
                                sign.pop();//直到栈顶元素为 '('结束并丢弃括号
                                break;
                            }
                            num.push(sign.pop());
                        }
                    }
                }
                else if(suffix[i] == '+' || suffix[i] == '-' || suffix[i] == '*' || suffix[i] == '/'){
                    if(sign.empty() || sign.peek() == '('){//为空或顶部元素为'('就直接压栈
                        sign.push(suffix[i]);
                    }
                    else{
                        if(isHighThan(suffix[i],sign.peek())){//当前的运算符比栈顶元素优先级高
                            sign.push(suffix[i]);
                        }
                        else{
                            while (true){
                                //遍历sign栈,将栈顶元素取出并压入num栈
                                // 直到遇到'('或者sign栈空 又或者找到一个元素优先级比当前元素高
                                if(sign.empty() || sign.peek() == '(' || isHighThan(suffix[i],sign.peek())) {
                                        sign.push(suffix[i]);
                                        break;
                                }
                                num.push(sign.pop());
                            }
                        }
                    }
                }
                else if(String.valueOf(suffix[i]).matches(PRE)){  //正则验证是否为是数字,直接入栈
                    num.push(suffix[i]);
                }
                else{
                    throw new RuntimeException(suffix[i]+"不是数字和运算符,请检查输入的算式是否正确");
                }
            }
            //遍历完成后,将sign剩余的所有符号依次出栈push到num栈中
            while (sign.size()>0) num.push(sign.pop());
    
            char[] result = new char[num.size()];
            //逆序获取num栈并保存到结果数组
            for(int lastIndex = result.length-1;num.size()>0;lastIndex--){
                result[lastIndex] = num.pop();
            }
            return result;
        }
    
    
        /**
         * 比较两个运算符的优先级signOb是否高于compareOb
         * @param signOb 要比较的符号
         * @param compareOb 比较的对象
         * @return true表示sign优先级高于compareOb
         */
        public static boolean isHighThan(char signOb,char compareOb){
            if((signOb == '+' || signOb == '-') && (compareOb == '*' || compareOb == '/'))//低于
                return false;
            else if((signOb == '+' || signOb == '-') && (compareOb == '+' || compareOb == '-')) //相同
                return false;
            else if((signOb == '*' || signOb == '/') && (compareOb == '*' || compareOb == '/')) //相同
                return false;
            else if((signOb == '*' || signOb == '/') && (compareOb == '+' || compareOb == '-')) //高于
                return true;
            else
                throw  new RuntimeException("该符号不是加减乘除:sign:"+signOb+",compareOb:"+compareOb);
        }
    
        /**
         * 比较两个运算符的优先级signOb是否高于或等于compareOb
         * @param signOb 要比较的符号
         * @param compareOb 比较的对象
         * @return true表示sign优先级高于compareOb
         */
        public static boolean isHighOrEqualThan(char signOb,char compareOb){
            if((signOb == '+' || signOb == '-') && (compareOb == '*' || compareOb == '/'))//低于
                return false;
            else if((signOb == '+' || signOb == '-') && (compareOb == '+' || compareOb == '-')) //相同
                return true;
            else if((signOb == '*' || signOb == '/') && (compareOb == '*' || compareOb == '/')) //相同
                return true;
            else if((signOb == '*' || signOb == '/') && (compareOb == '+' || compareOb == '-')) //高于
                return true;
            else
                throw  new RuntimeException("该符号不是加减乘除:sign:"+signOb+",compareOb:"+compareOb);
        }
    }
    

    测试类Main

    import java.util.*;
    public class Main {
        public static void main(String args[]){
            System.out.println("请输出四则混合运算表达式(仅限于个位数):");
            Calculator calc = new Calculator();
            Scanner scn = new Scanner(System.in);
            while(scn.hasNext()){
                String expres = scn.nextLine();
                System.out.println("请输入计算方式,Prefix(前缀)或Suffix(后缀):");
                String fix = scn.nextLine();
                System.out.println(calc.calculation(expres,fix));
            }
        }
    }

    测试结果如下图

    展开全文
  • http://acm.split.hdu.edu.cn/showproblem.php?pid=1805给你后缀表达式让你输出前缀表达式#include #include #include #include #define maxs 10010 #include #include <queue>
  • 后缀表达式前缀表达式

    千次阅读 2017-10-18 23:10:32
    后缀表达式前缀表达式是什么呢?  前缀表达式:不包括括号的算术表达式,将运算符写在前面,操作数写在后面的表达式。为纪念其发明者波兰数学家Jan Lukasiewcz,也称“波兰式”。  后缀表达式:不包括括号,...
  • 前缀表达式:/+A*BCD。 中缀表达式:A+B*C/D。 后缀表达式:ABC*+D/。 中缀表达式转换后缀表达式思路 操作数顺序不变,将运算符进行排序 将栈初始化为空栈; 从左到右扫描表达式的每一个字符,执行下面操作: ...
  • 后缀表达式 ABCD/-E*+ 中缀表达式与后缀表达式的区别: 运算数的顺序都是相同的 运算符的书写顺序不同,但真正的逻辑计算顺序相同 将中缀表达式 运算符的优先级 乘法(或除法)、取模运算 最高 加法...
  • 第二步:转换前缀后缀表达式 前缀:把运算符号移动到对应的括号前面 则变成拉:-( +(a *(bc)) +(de)) 把括号去掉:-+a*bc+de 前缀式子出现 后缀:把运算符号移动到对应的括号后面 则变成拉:((a(bc)* )- ...
  • 中缀表达式化后缀表达式:  (1+3)/8*3-5=  构建一个空运算符栈。先向里面压入一个'='(方便后边的比较)。然后从左向右扫描中缀表达式,如果是操作数,则直接输出即可;如果是左括号则直接入栈,如果是右括号,...
  • 中缀表达式就是我们数学中常用的那种表达式,本文打算以中缀表达式:1 + (2 + 3) × 4 - 5 为例,分享一下前缀表达式后缀表达式的如何形成与在计算机如何计算前后最表达式和后缀表达式 1、前缀表达式后缀表达式...
  • 中缀表达式前缀、后缀表达式,并计算其值2.1 中缀表达式转后缀表达式2.1.1 思路2.1.2 代码实现:2.2 中缀表达式转前缀表达式2.2.1 思路2.2.2 代码实现: 1.几种表达式的了解 1.1中缀表达式 1.1.1 定义 所谓的中缀...
  • 一、中缀表达式转后缀表达式 规则: 中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。 转换过程需要用到栈,具体过程如下: 1)如果遇到操作数,我们就直接将其输出。 2...
  • 之前总结了利用栈来将中缀表达式转为后缀与前缀表达式规则,并且附上了代码。最近复习到了树,正好使用二叉树来实现一下。 表达式树 表达式长成下面这个样子: 下图为: 后缀表达式 :ACB*+D/ 的表达式树。 前缀...
  • 1:什么是中缀表达式,前缀表达式后缀表达式? 正如我们常常潜意识认为我们所说的数字都是十进制,对于数字的其他进制感觉不正确一样,其实只是我们不熟悉而已,其他进制其实也不过就是一种对数据的表达方式而已...
  • 一、中缀表达式转后缀表达式这里的运算思路跟我代码一样,所以我就直接借鉴的别人的逆波兰表达式又称作后缀表达式,在四则混合运算的程序设计中用到。例如:1+2写成后缀表达式就是12+4+5*(3-2)的后缀表达式就是4532-...
  • 之前笔试中国电信IT研发中心的时候,遇到了几个前、中、后缀表达式的相互转换,当时忘得差不多了,今天好好把该方面的知识好好复习,并把相关代码和思路自己缕了一遍: 将中缀表达式转换为前缀表达式: 遵循以下...
  • 遇到操作符则存入栈中并且从表达式中删除该操作符,同时标记其匹配的操作数为0,如果遇到操作数,则应该对栈顶的操作符的配对操作数加一,当新来一个操作符时,对前面操作符的操作数配对期望降低,而对新来的操作...
  • 前缀表达式(波兰式):+ab 后缀表达式(逆波兰式):ab+ 表达式转换问题(考研经典) 一:手工转换 考研中有一类经典的问题就是表达式的转换问题,经常要把一个类型的表达式转换为另一个类型的表达式 所以这里我们...
  • 换出来树,前缀表达式后缀表达式只需要根据前序遍历和后续遍历即可得到,方便的很 目录 一、画树法 二、利用栈 例题:将中缀表达式a+b-a*((c+d)/e-f)+g转换为等价的后缀表达式ab+acd+e/f-*-g+。【2012年全国...
  • 本文运用c++实现了三种表达式求值 1.前缀表达式 :直接递归 2.后缀表达式:用栈 3.中缀表达式:转化为后缀表达式求值
  • 算术表达式中前缀表达式、中缀表达式、后缀表达式相互转换(手算法)
  • 中缀表达式中缀表达式是一种常用的算术或逻辑公式表示方法,操作符一中缀形式处于操作数中间。...例如:3+5+7-8前缀表达式运算符位于操作数之前 例如:-++3578后缀表达式:运算符位于操作符之后 例如: 35+
  • 中缀表达式、前缀表达式及后缀表达式中缀表达式前缀表达式中缀前缀过程后缀表达式中缀后缀过程 中缀表达式 我们一般写的表达式就为中缀表达式,如:ab/c+d, a+bc+d 前缀表达式 前缀表达式就是按次序把需要先算的...
  • 中缀转后缀表达式考虑表达式 A + B * C。A B C * +是等价的后缀表达式。 我们已经注意到,操作数 A,B 和 C 保持在它们的相对位置。只有操作符改变位置。再看中缀表达式中的运算符。从左到右出现的第一个运算符为 +...
  • 例如:中缀表达式(A+(B-C/D)*E)对应的前缀表达式是(+A*-B/CDE)对应的后缀表达式为(ABCD/-E*+) 说到转化之前我们先来看一下符号的优先级问题。 运算符 (左括号 +加,-减 *乘,/除,%取模 ^幂 ...
  • 1、把下列的后缀和前缀表达式转换为相应的中缀表达式 AB*C-D+ ABC+*D- +-*ABCD 2、利用栈把下列中缀表达式转换为后缀表达式前缀表达式 D-B+C A*B+C*D (A+B)*C-D*F+C

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 51,693
精华内容 20,677
关键字:

后缀表达式转前缀表达式的规则