用栈实现中缀表达式计算--逆波兰表达式计算

刚开始学,请大佬们看一看有没有啥问题。

"MyStack.h"

#pragma once
#include <iostream>
using namespace std;

template<class T>//结点 
class LinkNode
{
public:
	T data;//数据域
	LinkNode* next;//指针域
};

template<class T>
class LinkStack//栈
{
public:
	//初始化链栈
	LinkStack();
	//元素入栈
	void Push(T c);
	//元素出栈
	void Pop();
	//判断栈是否为空
	bool isEmpty();
	//获取栈顶元素,并用x接收
	T GetTop();
	//获取栈长度
	int Length();
private:
	LinkNode<T>* HeadNode;//头结点
	int len;
};

template<class T>
LinkStack<T>::LinkStack()
{
	HeadNode = new LinkNode<T>();
	HeadNode->next = NULL;
	len = 0;
}

//元素入栈
template<class T>
void LinkStack<T>::Push(T c)
{
	LinkNode<T>* p = new LinkNode<T>();
	p->data = c;
	p->next = HeadNode->next;
	HeadNode->next = p;
	++len;
}

//元素出栈
template<class T>
void LinkStack<T>::Pop()
{
	LinkNode<T>* p = HeadNode->next;
	if (p == NULL)
		return;
	HeadNode->next = p->next;
	delete p;
	--len;
}

//判断栈是否为空
template<class T>
bool LinkStack<T>::isEmpty()
{
	LinkNode<T>* p = HeadNode->next;
	if (p == NULL)
		return true;
	else
		return false;
}

//获取栈顶元素,并返回
template<class T>
T LinkStack<T>::GetTop()
{
	if (!isEmpty())
		return HeadNode->next->data;
	else
		return NULL;
}

//获取栈的长度
template <class T>
int LinkStack<T>::Length()
{
	return len;
}

 BracketMatch.h

#pragma once
#include <iostream>
using namespace std;

//判断输入的计算式括号是否合法
bool Bracket_isMatched(string str);
//输入计算式,储存在字符串str中
string EnString();

 BracketMatch.cpp

#include"MyStack.h"
#include"BracketMatch.h"
#include <iostream>
#include<string>
using namespace std;

//判断括号是否合法
/*
	1.初始化一个链栈,遍历传进来的字符串,
		遇到左括号则入栈,遇到右括号则:
			判断栈是否为空,若为空则表明不匹配;
			若栈不为空,将栈顶元素出栈,并检验是否与当前右括号匹配;
	2.遍历完成后,检验栈是否为空,若为空则括号匹配成功;否则,括号匹配失败
*/

//输入计算式,储存在字符串str中
string EnString()
{
	string str;
	getline(cin, str);
	return str;
}

//判断输入的计算式括号是否合法
bool Bracket_isMatched(string str)
{
	LinkStack<char> S;
	for (int i = 0; i != str.length(); ++i)
	{
		if (str[i] == '(' || str[i] == '[' || str[i] == '{')
			S.Push(str[i]);
		else if (str[i] == ')' || str[i] == ']' || str[i] == '}')
		{
			if (S.isEmpty())
				return false;
			else
			{
				char temp = S.GetTop();
				S.Pop();
				if (temp == '(' && str[i] != ')' || temp == '[' && str[i] != ']'
					|| temp == '{' && str[i] != '}')
					return false;
			}
		}
	}
	return S.isEmpty();
}

 Calculate.h 

#pragma once
#include <iostream>
#include"MyStack.h"
using namespace std;

//用栈计算中缀表达式
int Calculate();
//运算
int opera(int left, int right, char c);
//判断运算符优先级,判断c1优先级是不是小于或等于c2
bool Priority(char c1, char c2);
//弹出并获取一个运算符,弹出并获取操作数,计算之后将结果压入操作数栈
void GetCalculate(LinkStack<char>& S_char, LinkStack<int>& S_int);

 Calculate.cpp

#include<iostream>
#include"Calculate.h"
#include"BracketMatch.h"
#include"MyStack.h"

using namespace std;

/*
	1.用栈实现中缀表达式转后缀表达式
		初始化一个栈,用于保存暂时还不能确定运算顺序的运算符
		从左到右处理各个元素,直到末尾。可能遇到三种情况:
			①遇到操作数。直接加入后缀表达式;
			②遇到界限符。遇到"("直接入栈;遇到")"则一次弹出栈内运算符并加入
			后缀表达式,直到弹出"("为止。注意"("不加入后缀表达式
			③遇到运算符。依次弹出栈中优先级高于或等于当前运算符的所有运算符,
			并加入后缀表达式
*/
/*
	2.用栈实现后缀表达式计算
		1.从左往右扫描下一个元素,直到处理完所有元素
		2.若扫描到操作数则压入栈,并回到1.;否则执行3.
		3.若扫描到运算符。则弹出栈顶的连个元素,执行相应的运算,运算结果压回
		栈顶,回到1.
*/

/*
	3.用栈实现中缀表达式的计算
		初始化两个栈,操作数栈和运算符栈
		若扫描到操作数,则压入操作数栈
		若扫描到运算符或界限符,则按照“中缀转后缀相同的逻辑压入运算符栈(
		期间也会弹出运算符,每当弹出一个运算符时,就需要弹出两个操作数栈的
		栈顶元素并执行相应运算,运算结果再压回操作数栈)”
*/

//运算
int opera(int left,int right,char c)
{
	if (c == '+')
		return left + right;
	else if(c=='-')
		return left - right;
	else if(c=='*')
		return left * right;
	else if(c=='/')
		return left / right;
}

//弹出并获取一个运算符,弹出并获取操作数,计算之后将结果压入操作数栈
void GetCalculate(LinkStack<char>& S_char, LinkStack<int>& S_int)
{
	char c = S_char.GetTop();
		S_char.Pop();
		int left, right;
		//获取操作数
		right = S_int.GetTop();
		S_int.Pop();
		left = S_int.GetTop();
		S_int.Pop();
		//进行计算,并压入操作数栈
		S_int.Push(opera(left, right, c));
}

//判断运算符优先级,判断c1优先级是不是小于或等于c2
bool Priority(char c1, char c2)
{
		if ((c1 == '*' || c1 == '/') && (c2 == '+' || c2 == '-'))
			return false;
		else
			return true;
}

//用栈计算中缀表达式
int Calculate()
{
	string str = EnString();
	if (Bracket_isMatched(str))
	{
		LinkStack<char> S_char;//运算符栈
		LinkStack<int> S_int;//操作数栈
		int num = 0;
		int flag = 0;
		for (int i = 0; i != str.length(); ++i)
		{
			if(str[i] >= '0' && str[i] <= '9')//若遇到数字则将字符转换为数字
			{
				num = num * 10 + str[i] - '0';
				++flag;
				if (flag != 0 && i == str.length() - 1)
				{
					S_int.Push(num);//数字转换结束后压入操作数栈
					num = 0;//num清零
					flag = 0;
				}
			}
			else
			{
				if (flag != 0)//说明num被修改过
				{
					S_int.Push(num);//数字转换结束后压入操作数栈
					num = 0;//num清零
					flag = 0;
				}
				if (str[i] == '(')//遇到'('直接入运算符栈
					S_char.Push(str[i]);
				else if (str[i] == ')')
				{
					while (S_char.GetTop() != '(' )
					{
						GetCalculate(S_char, S_int);
					}
						S_char.Pop();
				}
				else if (str[i] == '+' || str[i] == '-' || str[i] == '*' ||
					str[i] == '/')
				{
						while (S_char.GetTop() != '('&& !S_char.isEmpty()
							&& Priority(str[i], S_char.GetTop()))
						{
								GetCalculate(S_char, S_int);
						}
						S_char.Push(str[i]);
				}
			}
		}
		while (!S_char.isEmpty())//判断操作符栈是否空,不空则进行计算
		{
			GetCalculate(S_char, S_int);
		}
		return S_int.GetTop();
	}
	else
	{
		cout << "括号不匹配" << endl;
		return -9999;
	}
}

 main.cpp

#include <iostream>
#include"MyStack.h"
#include"BracketMatch.h"
#include"Calculate.h"
using namespace std;

int main()
{
    cout << Calculate() << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值