数据结构之栈应用(中缀表达式转后缀表达式)

数据结构之栈应用(中缀表达式转后缀表达式)

 

目录

数据结构之栈应用(中缀表达式转后缀表达式)

代码实现

具体算法


 

代码实现

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>

using namespace std;

string infix,postfix;

typedef struct Node {
	int data;
	char str;
	struct Node *next;
}*linkstack;

typedef struct Lkstack {
	struct Node *top;
	int length;
}*Lstack;

void initstack(Lstack s);//初始化栈 
void Pushc(Lstack s,char e);//字符型数据入栈 
void Popc(Lstack s,char *e);//字符型数据出栈 
char Topc(Lstack s,char *e);//字符型栈顶元素 
void Pushn(Lstack s,int e);//整形数据入栈 
void Popn(Lstack s,int *e);//整形数据出栈 
int Topn(Lstack s,int *e);//整形栈顶元素 
int lenstack(Lstack s);//栈的长度 
char visit(char e);//输出一位栈中元素 
int stackTraverse(Lstack s);
int prio(char op);//运算符优先级排序
void Trans(string &str,string &str1,Lstack s);//中缀表达式转后缀表达式 
void calculation(Lstack s,int *e);//计算后缀表达式 

int main() {
	int ans=0;
	cout<<"输入四则表达式:	";
	cin>>infix;
	Lstack in=new Lkstack;
	initstack(in);
	Trans(infix,postfix,in);
	cout<<"后缀表达式:	"<<postfix<<endl;
	calculation(in,&ans);
	cout<<"计算结果:	"<<ans;
	return 0;
}

void initstack(Lstack s) {
	s->top=NULL;
	s->length=0;
	return;
}

void Pushc(Lstack s,char e) {
	linkstack l=new Node;
	l->str=e;
	l->next=s->top;
	s->top=l;//将新的节点l赋给栈顶指针
	s->length++;
	return;
}

void Popc(Lstack s,char *e) {
	if(s->length==0) return ;
	*e=s->top->str;
	s->top=s->top->next;
	s->length--;
}

char Topc(Lstack s,char *e) {
	*e=s->top->str;
	return *e;
}

void Pushn(Lstack s,int e) {
	linkstack l=new Node;
	l->data=e;
	l->next=s->top;
	s->top=l;//将新的节点l赋给栈顶指针
	s->length++;
	return;
}

void Popn(Lstack s,int *e) {
	if(s->length==0) return ;
	*e=s->top->data;
	s->top=s->top->next;
	s->length--;
}

int Topn(Lstack s,int *e) {
	*e=s->top->str;
	return *e;
}

int lenstack(Lstack s) {
	return s->length;
}

char visit(char e) {
	cout << e << "   ";
	return true;
}

int stackTraverse(Lstack s) {
	if (!lenstack(s)) {
		cout << "链表为空!" << endl;
		exit(0);
	}
	Lstack p;
	p = s;
	while (p->length) {
		visit(p->top->str);
	}
	cout << endl;
	return true;
}

int prio(char op) {                 //给运算符优先级排序
	int priority;
	if (op == '*' || op == '/')
		priority = 2;
	if (op == '+' || op == '-')
		priority = 1;
	if (op == '(')
		priority = 0;
	return priority;
}

void Trans(string &str,string &str1,Lstack s) {   //引用传递
	char c;
	for (unsigned int i = 0; i<str.length() ; i++) {
		if (str[i] >= '0' && str[i] <= '9') {    //如果是数字,直接入栈
			str1+=str[i];
		} else {                      //否则不是数字
			if(!lenstack(s))            //栈空则入站
				Pushc(s,str[i]);
			else if (str[i] == '(')   //左括号入栈
				Pushc(s,str[i]);
			else if (str[i] == ')') {  //如果是右括号,只要栈顶不是左括号,就弹出并输出
				while(s->top->str!='(') {
					str1+=Topc(s,&c);
					Popc(s,&c);
				}
				Popc(s,&c);                 //弹出左括号,但不输出
			} else {
				while (prio(str[i]) <= prio(Topc(s,&c))) { //栈顶优先级大于等于当前运算符,则输出
					str1+=c;
					Popc(s,&c);
					if (!lenstack(s))      //栈为空,停止
						break;
				}
				Pushc(s,str[i]);//把当前运算符入栈
			}
		}
	}
	while (lenstack(s)) {      //最后,如果栈不空,则弹出所有元素并输出
		str1+=Topc(s,&c);
		Popc(s,&c);
	}
}

void calculation(Lstack s,int *e) {
	int num=-1,a,b;
	for(int i=0; postfix[i]!='\0'; i++) {
		while(isdigit(postfix[i])) {
			num=postfix[i]-48;
			Pushn(s,num);
			num=0;
			i++;
		}
		switch(postfix[i]) {
			case '+': {
				Popn(s,&a);
				Popn(s,&b);
				Pushn(s,a+b);
				break;
			}
			case '-': {
				Popn(s,&a);
				Popn(s,&b);
				Pushn(s,b-a);
				break;
			}
			case '*': {
				Popn(s,&a);
				Popn(s,&b);
				Pushn(s,b*a);
				break;
			}
			case '/': {
				Popn(s,&a);
				Popn(s,&b);
				Pushn(s,b/a);
				break;
			}
		}
	}
	Popn(s,e);
}

具体算法

  1. 中缀表达式转后缀表达式

(1)如果遇到操作数,我们就直接将其输出。

(2)如果遇到操作符,则将其放入到栈中,遇到左括号时也将其放入栈中。

(3)如果遇到一个右括号,则将栈元素弹出,弹出的操作符输出直到遇到左括号为止,但左括号只弹出并不输出。

(4)如果遇到任何其他的操作符,如**(“+”, “*”,“(”)**等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。只有在遇到" ) “的情况下才弹出” ( “,其他情况都不弹出” ( "。

  (5)如果读到了输入的末尾,则将栈中所有元素依次弹出。

     2.  后缀表达式运算

           (1)将后缀表达式从左到右依次读取

           (2)如果读到数字直接入栈

(3)如果读到运算符,则将栈顶的两个数字出栈,和此运算符做运算,再将计算的结果压入栈中。(先入栈的数为减数,后入栈的数为被减数 用top减或除top-1,得到的结果压入top-1中)

           (4)重复上述步骤,最终的运算结果存在栈中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值