首页 > 编程知识 正文

c语言数据结构实现后缀表达式求值,c语言后缀表达式

时间:2023-05-03 15:54:57 阅读:44311 作者:3291

摘要:我来实验室两个星期了。 用强壮的啤酒来说,基本上是自拍状态。 勤奋的柠檬听说你向c学习了吗? 你能帮我做一个简单的计算器吗? 我想这台计算机一定没有只计算加减乘除那么简单。 因此仔细想想,为了写能使用括号的计算机,最好能写简单的UI。 考虑中发现,该计算机的难点在于如何将骑马订表达式转换为后缀表达式,以及如何计算后缀表达式。

计算的想法

人的想法

如果只是为了解决问题的话,这个方法最快也是正确的。 但不适用于计算机。 以下以AB*C(D*EF ) g为例,说明以下人员应该如何将骑马订格式转换为后缀格式:

按照先加减后乘除的原则在公式上加括号

结果: ((a ) b*c ) ) ) ) ) d*e ) f ) *g ) )

用后缀从内到外替换每个括号中的表达式

最终结果: abc* de*f g*

这将得到骑马订表达式转换为后缀表达式的最终结果。 该方法对应对试验有效。

计算机思维方式

毕竟电脑和别人不一样,是“笨蛋”啊。 别人的想法那样不能用。 那么,该如何将骑马订表达式转换为后缀表达式呢?

我的想法需要堆栈。 首先,明确从骑马订式到后缀式的转换规则。

1 )遇到操作数时,我们直接输出它。

2 )遇到操作员时放入堆栈,遇到左括号时也放入堆栈。

3 )如果检测到右括号,则弹出堆栈元素,并输出弹出的操作符直到检测到右括号。 请注意,左括号仅突出显示不会输出。

4 )遇到其他操作符(例如,()、()、()、()、()、()、()、()等)时,从堆栈弹出元素直到找到优先级更低的元素)或堆栈为空。 弹出这些元素后,将遇到的操作员推入堆栈。 有需要注意的事情。 只有在遇到“”“”时,我们才会弹出“”“”。 否则,不弹出“”“”。

5 )阅读输入末尾后,依次弹出堆栈中的所有元素。

以aB*c(d*ef ) g为例说明计算机的转换过程。 以下说明堆栈时,直接用文字记述,从左到右从堆栈底部到堆栈顶部。 天空表示堆栈天空

从左向右遍历公式,首先遇到a,然后直接输出。

此时的输出为a

对于堆栈,它为空

继续遍历,相遇,放入堆栈。

此时的输出为a

对于堆栈:

继续遍历,遇到b,直接输出它。

此时的输出为ab

对于堆栈:

继续遍历,遇到*。 *的优先级大于堆栈顶部,因此将*放入堆栈中。

此时的输出为ab

堆栈状况为*

继续遍历,遇到c,直接输出它。

此时的输出为abc

堆栈状况为*

继续遍历,遇到,的优先级低于堆栈顶部的*,弹出*; 而且,由于新堆栈顶的要素的优先顺序与该优先顺序相同,所以当前的堆栈顶的也必须弹出; 然后堆栈空了,现在把这个放进堆栈里。

此时的输出为abc*

对于堆栈:

继续遍历,(,直接放入堆栈,不遇到),即使遇到)不弹。

此时的输出为abc*

对于堆栈,请使用(

继续遍历,遇到d,直接输出它。

此时的输出为abc* d

对于堆栈,请使用(

继续遍历,遇到*。 栈顶为(,不遇到) ),因此将)直接放入栈中。

此时的输出为abc* d

对于堆栈,请单击(*

继续遍历,遇到e,直接输出它。

此时的输出为abc* de

对于堆栈,请单击(*

继续遍历,遇到,优先级低于堆栈顶部*,弹出*; 新堆栈的最上面的元素是(,不遇到),不出去),因此将其放入堆栈中。

此时的输出为abc* de*

对于堆栈,请使用(

继续遍历,遇到f,直接输出它。

此时的输出为abc* de*f

对于堆栈,请使用(

遍历,遇到),然后直接按顺序弹出堆栈中的元素,直到遇到()为止。 )。 )弹出,但不输出。

此时的输出为abc* de*f

对于堆栈:

继续遍历,遇到*。 *的优先级大于堆栈顶部元素的优先级,因此直接将*放入堆栈中。

此时的输出为abc* de*f

堆栈状况为*

继续遍历,遇到g,直接输出。

此时的输出为abc* de*f g

堆栈状况为*

继续遍历,清空,结束遍历。 按顺序弹出堆栈中的元素。

此时的输出为abc* de*f g*

对于堆栈,它为空

现在,所有骑马订后缀都已完成,结果为abc* de*f g*。

代码实现

源代码

代码是用c写的,但还是用了面向过程的思路。 代码如下。

//骑马订式后缀

#包含

#包含

#包含

用户命名空间STD;

p>

int prio(char op) { //给运算符优先级排序

int priority;

if (op == '*' || op == '/')

priority = 2;

if (op == '+' || op == '-')

priority = 1;

if (op == '(')

priority = 0;

return priority;

}

bool Trans(string &str,string &str1) { //引用传递

stack s; //定义一个char类型的栈s

int i;

for (i = 0; i

if (str[i] >= '0' && str[i] <= '9') { //如果是数字,直接入栈

str1+=str[i];

}

else { //否则不是数字

if (s.empty()) //栈空则入站

s.push(str[i]);

else if (str[i] == '(') //左括号入栈

s.push(str[i]);

else if (str[i] == ')') { //如果是右括号,只要栈顶不是左括号,就弹出并输出

while (s.top() != '(') {

str1+= s.top();

s.pop();

}

s.pop(); //弹出左括号,但不输出

}

else {

while (prio(str[i]) <= prio(s.top())) { //栈顶优先级大于等于当前运算符,则输出

str1+= s.top();

s.pop();

if (s.empty()) //栈为空,停止

break;

}

s.push(str[i]); //把当前运算符入栈

}

}

}

while (!s.empty()) { //最后,如果栈不空,则弹出所有元素并输出

str1+= s.top();

s.pop();

}

return true;

}

int main() { //主程序

string infix;

string postfix;

cout << "请输入中缀表达式:" << infix << endl;

cin >> infix;

Trans(infix,postfix);

cout << "后缀表达式为:" << postfix << endl;

return 1;

}

程序测试

这里我们就用a+b*c+(d*e+f)*g的实例1+2*3+(4*5+6)*7来测试我们的程序,可见运行结果为123*+45*6+7*+,计算正确。

intopost.png

总结

在写这段小程序时有一些不小的收获。毕竟是一个初学者,犯的错误都是很低级的知识性错误,理解不到位,基础不扎实。这里要感谢我的本科同学白洋耐心地教我。

1)string类的对象在没有初始化大小的情况下不要用其下标运算,会出现string subscript out of range(下标越界)的错误。在第三次执行循环时出现,大概是因为string对象的默认大小为2个字节。

2)string类的对象不以''结尾,要与C语言区分开来,判断其结束时用size()函数。size() 函数返回的是其大小,然后下标是以0开始的,所以最大到size-1。

3)函数调用进行形实结合时要用引用传递。

4)#include的使用。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。