逆波兰表达式[栈 C 语言 实现]

逆波兰表达式

逆波兰表达式又叫做后缀表达式。在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示。波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示表达式的方法,按此方法,每一运算符都置于其运算对象之后,故称为后缀表示。

 

a+b ---> a,b,+

a+(b-c) ---> a,b,c,-,+

a+(b-c)*d ---> a,b,c,-,d,*,+

a+d*(b-c)--->a,d,b,c,-,*,+

1、将一个中序表达式转化成为逆波兰表达式

 

构造两个栈S1,S2,S1用来存放表达式,S2用来暂时存放运算符,最后完成后,该栈是清空的。

(1)如果遇到的是数字,直接进栈S1

(2)如果遇到的是左括号,进栈S2

(3)如果遇到的是右括号,将S2中的运算符全部出栈压入S1中,注意括号不压入

(4)如果遇到的运算符

 

         1.如果此时栈S2为空,则直接将运算符加入到栈S2中;

         2.如果此时栈S2不为空,当前运算符的优先级大于等于栈顶运算符的优先级,那么直接入栈S2;

         3.如果此时栈S2不为空,当前运算符的优先级小于栈顶运算符的优先级,则将栈顶运算符一直出栈压入到栈S1中,  直到栈为空或者遇到一个运算符的优先级小于等于当前遍历的运算符的优先级,然后将该运算符压入到栈S2中。    

(5)遍历完整个中序表达式之后,如果栈S2中仍然存在运算符,那么将这些运算符依次出栈压入到栈S1中,直到栈为空。

2、利用逆波兰表达式求值

 

维护一个结果栈S3,该栈最后存放的是表达式的值。从左至右的遍历栈S1

(1)如果遇到的是数字,直接将数字压入到S3中

(2)如果遇到的是单目运算符,取S3栈顶的一个元素进行运算之后,将结果压入到栈S3中

(3)如果遇到的是双目运算符,取S3栈顶的两个元素,首先出栈的在左,后出栈的在右进行双目运算符的计算,将结果压入到S3中

遍历完整个栈S1,最后S3中的值就是逆波兰表达式的值。

 

栈实现表达式计算【数据结构】

思路:

所包含的运算符有‘+’,‘-’,‘*’,‘/’,‘(’,‘)’。

(1)建立两个栈,一个用来存储操作数,另一个用来存储运算符, 开始时在运算符栈中先压入‘/0’,一个表达式的结束符。

(2)然后从左至右依次读取表达式中的各个符号(操作数或者运算符);

(3)如果读到的是操作数直接存入操作数栈;

(4)如果读到的是运算符,则作进一步判断:

若读到的是‘/0’结束符,而且此时运算符栈的栈顶元素也是‘/0’结束符,则运算结束,输出操作数栈中的元素即为最后结果。

若读到的是‘(’或者读到的运算符的优先级比目前的运算符栈中的栈顶元素的优先级高,则将运算符直接存入运算符栈,继续读表达式中的下一个符号,重复步骤(3)和(4);

若读到的是‘)’,而且此时运算符栈的栈顶元素是‘(’结束符,则将运算符栈中的栈顶元素退出来,继续读表达式中的下一个符号,重复步骤(3)和(4);

若读到的运算符的优先级等于或小于之前的运算符的优先级,则从操作数中退出2个,从运算符中退出一个进行运算,将运算结果存入操作数栈;再把之前读到的运算符与目前的运算符栈顶比较,重复步骤(4)(即现在不读下一个元素);

 

/*
输入:
9+(3-1)*3+10/2 

输出
20

注意:其实注释的地方可以用来调试,本人主要根据大话数据结构的思路写出来的
        如果有什么地方错了,多谢提出。
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
struct stack{
	char data[101];
	int top;
};

struct stack2{
	int data1[101];
	int top;
}; 


struct stack tak;
struct stack2 tak2;

bool jia(char s){
	if(s=='+' || s=='-')
		return true;
	else 
		return false;
}
bool ch(char s){
	if(s=='*' || s=='/')
		return true;
	else 
		return false;
}
int number(int y, int x, char s){
	if(s=='+')
		return x + y;
	if(s=='-')
		return x - y;
	if(s=='*')
		return x * y;
	if(s=='/' )
		return x / y; 
}

int main(){
	char s1[20];
	
	scanf("%s",&s1);
	getchar();
	
	
	
	tak.top = 0;
	tak2.top = 0;
	
	//中缀表达式转化为后缀表达式 
	for(int i=0;i<strlen(s1);i++){
	
		if(s1[i]>='0' && s1[i]<='9'){
			int tep = s1[i]-'0';
		
			while(s1[i+1]>='0' && s1[i+1]<='9'){
				tep *= 10;
				i++;
				tep += s1[i]-'0'; 
			}
//			printf("%d ",tep);
			
			tak2.top++;
			tak2.data1[tak2.top] = tep;
			
			
			
			
			
		}else{
			if(tak.top==0 || tak.data[tak.top]=='('){
				tak.top++;
				tak.data[tak.top] = s1[i];
			}else{
				char temp = tak.data[tak.top];
				
				if( jia(temp) && (ch(s1[i]) || jia(s1[i]) || s1[i]=='(')  ){
					tak.top++;
					tak.data[tak.top] = s1[i];	 
				}else if(ch(temp) && (ch(s1[i]) || s1[i]=='(')){
					tak.top++;
					tak.data[tak.top] = s1[i];
				}else if(s1[i]==')'){
	
					while(tak.top>0){
					
						if(tak.data[tak.top]=='('){
							tak.top--;
							break;
						}
//						printf("%c ",tak.data[tak.top]);
						
						int t1 = tak2.data1[tak2.top];
						tak2.top--;
						int t2 = tak2.data1[tak2.top];
						int t3 = number(t1,t2,tak.data[tak.top]);
						
						tak2.data1[tak2.top] = t3;
						
			
						
						
						
						tak.top--;
					}
					
				}else if(ch(temp) && jia(s1[i])){
					while(tak.top>0){
						if(tak.data[tak.top]=='('){
							break;
						}
//						printf("%c ",tak.data[tak.top]);
						
						
						int t1 = tak2.data1[tak2.top];
						tak2.top--;
						int t2 = tak2.data1[tak2.top];
						int t3 = number(t1,t2,tak.data[tak.top]);
						tak2.data1[tak2.top] = t3;
						
					
						
						
						
						tak.top--;
					}
					tak.top++;
					tak.data[tak.top] = s1[i];
				}
			}	
		} 
	}

	while(tak.top>0){
//		printf("%c ",tk.data[tak.top]);
		
		int t1 = tak2.data1[tak2.top];
		tak2.top--;
		int t2 = tak2.data1[tak2.top];
		int t3 = number(t1,t2,tak.data[tak.top]);
		tak2.data1[tak2.top] = t3;
//		cout<<"  t3 = "<<t3<<endl;
		
		tak.top--;
	}

	printf("%d",tak2.data1[tak2.top]);
	
	
	return 0; 
}

 

好的,下面是一个简单的逆波兰表达式求值的 C 语言程序。假设输入的逆波兰表达式已经存储在一个字符数组中,程序使用实现求值。 ```c #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define MAX_STACK_SIZE 100 int stack[MAX_STACK_SIZE]; int top = -1; int is_operator(char c) { return (c == '+' || c == '-' || c == '*' || c == '/'); } void push(int n) { if (top >= MAX_STACK_SIZE - 1) { fprintf(stderr, "Error: Stack overflow\n"); exit(EXIT_FAILURE); } stack[++top] = n; } int pop() { if (top < 0) { fprintf(stderr, "Error: Stack underflow\n"); exit(EXIT_FAILURE); } return stack[top--]; } int evaluate(char *expr) { int i, op1, op2, result; char c; for (i = 0; expr[i] != '\0'; i++) { c = expr[i]; if (isdigit(c)) { push(c - '0'); } else if (is_operator(c)) { op2 = pop(); op1 = pop(); switch (c) { case '+': push(op1 + op2); break; case '-': push(op1 - op2); break; case '*': push(op1 * op2); break; case '/': push(op1 / op2); break; } } } result = pop(); if (top >= 0) { fprintf(stderr, "Error: Invalid expression\n"); exit(EXIT_FAILURE); } return result; } int main() { char expr[] = "3 4 + 5 * 6 -"; // 示例表达式 int result = evaluate(expr); printf("Result = %d\n", result); return 0; } ``` 这个程序使用了实现逆波兰表达式求值,先遍历逆波兰表达式中的每个字符,若是数字则入,若是运算符则弹出顶的两个元素进行运算,并将结果入。最终,中只剩下一个元素,即为表达式的值。注意,这个程序并没有进行错误处理,例如输入表达式中出现非法字符或溢出等情况。在实际使用中,需要根据具体情况进行错误处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值