表达式求值(中缀转后缀及后缀表达式求值)

表达式求值(中缀转后缀及后缀表达式求值)。中缀表达式转后缀表达式:中缀表达式转后缀表达式遵循以下原则:1.遇到操作数,直接输出;2.栈为空时,遇到运算符,入栈;3.遇到左括号,将其入栈;4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;5.遇到其他运算符’+”-”*”/’时,弹出所有优先级大于或等于该运

大家好,又见面了,我是你们的朋友全栈君。

。中缀表达式转后缀表达式:

中缀表达式转后缀表达式遵循以下原则:

1.遇到操作数,直接输出;
2.栈为空时,遇到运算符,入栈;
3.遇到左括号,将其入栈;
4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;
5.遇到其他运算符’+”-”*”/’时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈;
6.最终将栈中的元素依次出栈,输出。
经过上面的步骤,得到的输出既是转换得到的后缀表达式。
举例:a+b*c+(d*e+f)g ———> abc+de*f+g*+

图示上述过程:

因为比较懒,而刚好在网上看到画的还不错的图,所以就直接贴过来了哦。希望作者不要怪罪哦。。。
遇到a,直接输出:

这里写图片描述

遇到+,此时栈为空,入栈:
这里写图片描述

遇到b,直接输出:
这里写图片描述
遇到*,优先级大于栈顶符号优先级,入栈:
这里写图片描述

遇到c,输出:
这里写图片描述
到+,目前站内的与+优先级都大于或等于它,因此将栈内的,+依次弹出并且输出,并且将遇到的这个+入栈:
这里写图片描述
遇到(,将其入栈:
这里写图片描述

遇到d,直接输出:
这里写图片描述
遇到*,由于的优先级高于处在栈中的(,因此入栈:
这里写图片描述
遇到e,直接输出:
这里写图片描述
遇到+,栈顶的优先级高于+,但是栈内的(低于+,将出栈输出,+入栈:这里写图片描述

遇到f,直接输出:
这里写图片描述
遇到),弹出栈顶元素并且输出,直到弹出(才结束,在这里也就是弹出+输出,弹出(不输出:
这里写图片描述
遇到*,优先级高于栈顶+,将*入栈
这里写图片描述
遇到g,直接输出: :
这里写图片描述
此时已经没有新的字符了,依次出栈并输出操作直到栈为空:
这里写图片描述

因为后缀表达式求值过程较为简单:
所以在这里我只进行简单说明:
1.扫描后缀表达式:
①如果是数字,则让其进栈
②若为操作符,则从栈中取出两个操作数,先取出的作为右操作数,后取出的作为左操作数,然后进行该操作符的运算,并使其结果入栈。
③重复上述过程,直至表达式扫描完成。
2.最终栈中只留一个元素—–>即就是结果。

下面代码实现中缀转后缀以及后缀表达式求值:

使用的栈是自定义栈(自己实现的):
//stack.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include<cassert>
//------------使用类型萃取来拷贝栈内元素-------------
struct _TrueType
{
bool Get()
{
return true;
}
};
struct _FalseType
{
bool Get()
{
return false;
}
};
template<class _Tp>
struct TypeTraits
{
typedef _FalseType _IsPODType;
};
template<>
struct TypeTraits<bool>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<int>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<unsigned int>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<char>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits< float >
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits< double >
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<long>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits< unsigned long>
{
typedef _TrueType _IsPODType;
};
template<class T>
void Copy(T* dst, T* src, size_t size)
{
if (TypeTraits<T>::_IsPODType().Get())
{
memcpy(dst, src, size);
}
else
{
for (int i = 0; i < size; ++i)
{
dst[i] = src[i];
}
}
}
template<class T>
struct TypeTraits< T* >
{
typedef _TrueType _IsPODype;
};
//-------------------------栈的基本操作----------------
template<class T>
class Stack
{
public:
//构造函数
Stack(int capacity = 10)
:_pData(NULL)
, _capacity(capacity)
, _size(0)
{
_pData = new T[capacity];
}
//拷贝构造函数
Stack(const Stack<T>& s)
:_pData(new T[s._capacity])
, _size(s._size)
, _capacity(s._capacity)
{
for (int i = 0; i < _size; ++i)
{
_pData[i] = s._pData[i];
}
}
//赋值运算符函数
Stack& operator=(Stack<T> s)
{
std::swap(_pData, s._pData);
_size = s._size;
_capacity = s._capacity;
return *this;
}
//入栈
void Push(const T& data)
{
CheckCapacity();
_pData[_size++] = data;
}
//出栈
void Pop()
{
if (!Empty())
{
--_size;
}
}
//获取栈顶元素
T& Top()
{
if (!Empty())
{
return _pData[_size - 1];
}
}
const T& Top()const
{
if (!Empty())
{
return _pData[_size - 1];
}
}
size_t Size()const
{
return _size;
}
bool Empty()const
{
return 0 == _size;
}
//析构函数(释放资源)
~Stack()
{
if (_pData)
{
delete[] _pData;
_pData = NULL;
}
}
private:
//增容
void CheckCapacity()
{
if (_size >= _capacity)
{
_capacity = 2 * _capacity + 3;
T* tmp = new T[_capacity];
//拷贝原数据
//释放旧空间
//指向新空间
//需要进行类型萃取
Copy<T>(_pData, tmp, _size);
delete[] _pData;
_pData = tmp;
}
}
T* _pData;
int _capacity;
int _size;
};
//----------------------------------------------------------
//需要用到的函数的声明
int GetPriority(char ch, int flag);//获取优先级
bool IsOperator(char ch);//判断是否为操作符
void prefixionToSuffix(char* dst, char* src);//中缀表达式转后缀表达式
int  SuffixToValue(char *suffix, char *prefixion);//后缀表达式求值

中缀表达式转后缀表达式:
//prefixionToSuffix.cpp

#include"Stack.h"
//flag为1时表示栈内优先级  flag为0表示栈外优先级
int GetPriority(char ch, int flag)
{
if (ch == '+' || ch == '-')
{
if (flag)
{
return 3;
}
else
{
return 2;
}
}
else if (ch == '*' || ch == '/' || ch == '%')
{
if (flag)
{
return 5;
}
else
{
return 4;
}
}
else if (ch == '(')
{
if (flag)
{
return 1;
}
return 6;
}
else if (ch == ')')
{
if (flag)
{
return 6;
}
else
{
return 1;
}
}
}
bool IsOperator(char ch)
{
if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%' || ch == '(' || ch == ')')
{
return true;
}
return false;
}
//中缀表达式转后缀表达式
void prefixionToSuffix(char* dst, char* src)
{
assert(dst);
assert(src);
Stack<char> s;
char * cur = src;
char* tmp = dst;
while (*cur != '\0')
{
if (*cur >= '0' && *cur <= '9')
{
*tmp++ = *cur;
cur++;
continue;
}
else if (IsOperator(*cur))
{
if (s.Empty())//如果栈为空,直接入栈
{
s.Push(*cur);
cur++;
}
else//如果栈不空,则需要判断栈顶元素和当前操作符的优先级
{
if (*cur == ')')
{
while (*cur == ')' && s.Top() != '(')
{
*tmp++ = s.Top();
s.Pop();
}
s.Pop();
cur++;
}
if (GetPriority(*cur, 0) > GetPriority(s.Top(), 1))
{
s.Push(*cur);
cur++;
}
else
{
while (!s.Empty() && GetPriority(*cur, 0) < GetPriority(s.Top(), 1))
{
*tmp++ = s.Top();
s.Pop();
}
s.Push(*cur);
cur++;
}
}
}
else
{
*tmp++ = *cur++;
}
}
while(!s.Empty())
{
*tmp++ = s.Top();
s.Pop();
}
}

后缀表达式求值:
//SuffixToValue.cpp

#include"Stack.h"
//12 3 4 + * 6 - 8 2 / +
int  SuffixToValue(char *suffix, char *prefixion)
{
prefixionToSuffix(suffix, prefixion);
Stack<int> s;
char* cur = suffix;
int res = 0;
int tmp = 0;
while (*cur != '\0')
{
if (*cur == '+' || *cur == '-' || *cur == '*' || *cur == '/' || *cur == '%')
{
char ch = *cur;
int right = s.Top();
s.Pop();
int left = s.Top();
s.Pop();
switch (ch)
{
case '+':
s.Push(left + right);
break;
case '-':
s.Push(left - right);
break;
case '*':
s.Push(left * right);
break;
case '%':
s.Push(left % right);
break;
case '/':
if (right)
{
s.Push(left / right);
}
break;
}
cur++;
}
else if (*cur >= '0' && *cur <= '9')
{
res = 0;
while (!isspace(*cur) && *cur >= '0' && *cur <= '9')
{
tmp = *cur - '0';
res = res * 10 + tmp;
cur++;
}
s.Push(res);
//cur++;
}
else
{
cur++;
}
}
if (!s.Empty())
{
res = s.Top();
return res;
}
}

main.cpp

#include"Stack.h"
void Test()
{
char prefixion[] = "12 * (3 + 4) - 6 + 8 / 2 ";//保存前缀表达式
char suffix[25] = {};//保存后缀表达式
int res = SuffixToValue(suffix, prefixion);
cout << res << endl;
}
int main()
{
Test();
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/149735.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 模电基础部分总结(自用)

    模电基础部分总结(自用)模电基础部分总结(自用)第一章1.1半导体基础知识1.什么是模拟信号,数字信号?答:模拟信号在时间和数值上均具有连续性,例如正弦波信号。模拟信号在时间和数值上均具有连散性,它们的数值是最小量值的整倍数,并以此倍数作为数字信号的数值。2模/数转换,数/模转换?答:模数:对模拟信号进行数字化处理时,需首先将其转换成计算机识别的数字信号。数模:计算机输出的数字信号常需转换为能够驱动负载的…

  • request.setAttribute和session.setAttribute的区别「建议收藏」

    request.setAttribute和session.setAttribute的区别「建议收藏」1.request.setAttributerequest.setAttribute作用域是请求和被请求页面之间,只在此action的下一个forward需要使用时候调用;request.setAttribute()可存放的参数是String和Object。req.setAttribute(“maps”,maps);//请求转发,携带数据,req存储数据req.getRequestDispatcher(“/user.jsp”).forward(req,resp);2、session.setA

    2022年10月17日
  • jQuery可拖拽3D万花筒旋转特效

    这是一个使用了CSS3立体效果的强大特效,本特效使用jQuery跟CSS3transform来实现在用户鼠标按下拖动时,环形图片墙可以跟随鼠标进行3D旋转动画。效果体验:http://hovertr

    2021年12月28日
  • ES 最佳实践配置

    ES 最佳实践配置

    2021年11月27日
  • RocketMQ探索序言

    RocketMQ探索序言

  • 【C#】 Mutex简单示例

    【C#】 Mutex简单示例Mutex简单示例:namespaceMutexTest{classProgram{//用于Mutex的TeststaticvoidMain(string[]args){System.Security.Cryptography.MD5md5=newSystem.Securi…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号